当前位置: 首页 > 知识库问答 >
问题:

对远程web服务的Spring Boothttp调用

袁琪
2023-03-14

我必须使用SpringBoot2.0.5从web应用程序构建中调用远程RESTendpoint

我可以使用HttpURLConnection,但由于Spring使用RestTemplate,我检查了它是什么,发现它很快就会被弃用:

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html

本页还提到了要通过HTTP调用的新类。可以以同步和异步两种方式使用它:

WebClient为RestTemplate提供了一种现代的替代方案,对同步和异步以及流式场景都提供了高效的支持

问题是我在javadoc for WebClient中没有看到任何关于同步方式的注释:

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.html

WebClient还有一个问题-为了让它工作,我需要在类路径中设置WebFluxhttps://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-webclient.html

但这将阻止我的Spring Security配置以同步方式构建。据我所知,一旦我有了WebFlux,Spring Security性将使用异步配置。

如何使用Spring对远程endpoint进行http调用,或者应该避免使用HttpURLConnection类(或Apache的库)?

最新消息

WebFlux似乎不会导致任何问题与Spring Security buit同步的方式。

另外请注意,我的应用程序不是反应性的——它是多线程的(抱歉,如果我之前不清楚这一点)。我有如此被动的交易方法似乎不适合我的情况。

共有2个答案

轩辕源
2023-03-14

您可以使用SpringCloud提供的技术。例如,对于请求其他web服务,最好的方法是使用假客户端。对于处理Hystrix的异常。

墨宜人
2023-03-14

您可以使用Spring组织。springframework。网状物客户异步Rest调用的AsyncRestTemplate。下面是我用于同步和异步调用的实用程序之一。下面是异步的Rest实用程序和回调。

/**
 *
 */
package com.debopam.services.policyenquiryservice.rest.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.client.AsyncRestTemplate;

/**
 * @author dpoddar
 *
 */
public class RestUtil {

    private String url;
    private HttpMethod httpMethod;
    private MultiValueMap<String, String> headers;
    private Map<String, Object> params;
    private Class<?> responseType;
    private List<Object> uriVariables;

    private HttpEntity<Object> httpEntity;

    //AsyncRestTemplate asyncRestTemplate = (AsyncRestTemplate) ContextProvider.getBean("customAsyncRestTemplate");

    /**
     * @param url
     * @param httpMethod
     * @param headers
     * @param params
     * @param responseType
     * @param uriVariables
     */
    public RestUtil(String url, HttpMethod httpMethod, MultiValueMap<String, String> headers,
            Map<String, Object> params, Class<?> responseType, List<Object> uriVariables) {
        super();
        this.url = url;
        this.httpMethod = httpMethod;
        this.headers = headers;
        this.params = params;
        this.responseType = responseType;
        this.uriVariables = uriVariables;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Foo callServicesync(RestTemplate restTemplate) {

        //DO a sync Call
        HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
        Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class);

    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void callServiceAsync(AsyncRestTemplate asyncRestTemplate,ResponseCallBack responseCallBack) {

        if(asyncRestTemplate.getMessageConverters().isEmpty()){
            asyncRestTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
        }

        ListenableFuture restCall = null;
        if(null != uriVariables){
            restCall = asyncRestTemplate.exchange(this.url, this.httpMethod, this.httpEntity, responseType,uriVariables);
        }else{
            restCall = asyncRestTemplate.exchange(this.url, this.httpMethod, this.httpEntity, responseType);
        }

        restCall.addCallback(responseCallBack);

    }

    public static class RestUtilBuilder {
        private String url;
        private HttpMethod httpMethod;
        private MultiValueMap<String, String> headers;
        private Map<String, Object> params;
        private Class<?> responseType;
        private List<Object> uriVariables;

        public RestUtilBuilder url(String url) {
            this.url = url;
            return this;
        }

        public RestUtilBuilder httpMethod(HttpMethod httpMethod) {
            this.httpMethod = httpMethod;
            return this;
        }

        public RestUtilBuilder headers(MultiValueMap<String, String> headers) {
            this.headers = headers;
            return this;
        }

        public RestUtilBuilder addHeader(String key,String value) {
            if(null == this.headers){
                this.headers = new LinkedMultiValueMap<>();
            }
            this.headers.add(key, value);
            return this;
        }

        public RestUtilBuilder params(Map<String, Object> params) {
            this.params = params;
            return this;
        }

        public RestUtilBuilder addparam(String key,Object value) {
            if(null == this.params){
                this.params = new HashMap<>();
            }
            this.params.put(key, value);
            return this;
        }

        public RestUtilBuilder responseType(Class<?> responseType) {
            this.responseType = responseType;
            return this;
        }

        public RestUtilBuilder uriVariables(List<Object> uriVariables) {
            this.uriVariables = uriVariables;
            return this;
        }

        public RestUtil build() {
            RestUtil util = new RestUtil(url, httpMethod, headers, params, responseType, uriVariables);
            util.httpEntity = new HttpEntity<Object>(util.params, util.headers);
            return util;
        }
    }

    public static RestUtilBuilder restUtil() {
        return new RestUtilBuilder();
    }

}



package com.debopam.services.policyenquiryservice.rest.util;

import java.util.Map;
import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.http.ResponseEntity;
import org.springframework.util.concurrent.ListenableFutureCallback;

/**
Response Call back for Async Call
*/
public abstract class ResponseCallBack<T> implements ListenableFutureCallback<ResponseEntity<T>>{

    private static final Logger logger = LoggerFactory.getLogger(ResponseCallBack.class.getName());

    Map<String,Object> inputs;


    public ResponseCallBack(Map<String,Object> inputs){
        this.inputs = inputs;
    }

    @Override
    public void onSuccess(ResponseEntity<T> stringResponseEntity) {
        onCallSuccess(this.inputs,stringResponseEntity);
    }

    @Override
    public void onFailure(Throwable ex) {
        logger.error(ex.getMessage(),ex);
        onCallFailure(this.inputs, ex);
    }

    //Do your stuff
    public abstract void onCallSuccess(Map<String,Object> inputs,ResponseEntity<T> stringResponseEntity);
    public abstract void onCallFailure(Map<String,Object> inputs,Throwable ex);
}

//Example
private void createRestUtilForAsync()
    {

    RestUtil restUtil = RestUtil.restUtil().url(url).addHeader("Accept", "application/json").addHeader("Content-Type", "application/json").addparam("xxx", 10).addparam("yyyy", "").addparam("zzz", "dsadsa").httpMethod(HttpMethod.POST).responseType(Policy.class).build();
    //create inputs
    ResponseCallBack<Policy> responseCallBack = new ResponseContractValuesCallBack(inputs);

    //asyncRestTemplate is autowired in the class
    restUtil.callServiceAsync(this.asyncRestTemplate, responseCallBack);
}

private void createRestUtilForSync()
    {

    RestUtil restUtil = RestUtil.restUtil().url(url).addHeader("Accept", "application/json").addHeader("Content-Type", "application/json").addparam("xxx", 10).addparam("yyyy", "").addparam("zzz", "dsadsa").httpMethod(HttpMethod.POST).responseType(Policy.class).build();

    //asyncRestTemplate is autowired in the class
    Foo foo = restUtil.callServiceAsync(this.restTemplate);
}
 类似资料:
  • 答案可能涵盖所有框架,但我对SpringMVC案例特别感兴趣。我正在重构一个访问内部数据库和远程服务的服务层。这些方法应该是事务性的,它们需要来自远程服务的数据。下面是类似的伪代码: 这样更容易实现。但是有许多缺点,例如当远程服务调用失败时不必要地创建和回滚事务,由于远程服务调用而导致的事务更长,并且可能更复杂。我正在考虑将服务调用移动到单独的非事务性方法,并调用事务性方法,如下面的代码段所示 假

  • 主要内容:1.概述,2. HttpClientConnection,3. HessianProtocol1.概述 Hessian 协议用于集成 Hessian 的服务,Hessian 底层采用 Http 通讯,采用 Servlet 暴露服务,Dubbo 缺省内嵌 Jetty 作为服务器实现。 本文涉及类图(红圈部分)如下: 2. HttpClientConnection 实现 HessianConnection 接口,HttpClient 连接器实现类。 2.1 HttpClientConnec

  • 主要内容:1. 概述,2. AbstractProxyProtocol,3. HttpProtocol1. 概述 基于 HTTP 表单的远程调用协议,采用 Spring 的 HttpInvoker 实现 涉及类图(红圈部分)如下: 2. AbstractProxyProtocol 现 AbstractProtocol 抽象类,Proxy 协议抽象类。为 HttpProtocol 、RestProtocol 等子类,提供公用的服务暴露、服务引用的公用方法,同时定义了如下抽象方法,用于不同子类协议实

  • 主要内容:1.概述,2. 消费者调用服务,3. 提供者提供服务1.概述 在 dubbo:// 协议的调用,一共分成三种: sync 同步调用 async 异步调用 oneway 单向调用 前两种比较好理解,都是基于 Request Response 模型,差异点在异步调用,服务消费者不阻塞等待结果,而是通过回调的方式,处理服务提供者返回的结果。 最后一种,基于 Message 模型,发起调用,而不关注等待和关注执行结果。 因此,从性能上:oneway > a