Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >springboot实战之常用http客户端整合

springboot实战之常用http客户端整合

作者头像
lyb-geek
发布于 2019-11-12 07:13:18
发布于 2019-11-12 07:13:18
8.1K03
代码可运行
举报
文章被收录于专栏:Linyb极客之路Linyb极客之路
运行总次数:3
代码可运行
前言

本文主要介绍一下三种http客户端,httpcomponents项目下的httpclient(后边简化描述为httpcomponents-client)、restTemplate、webclient的基本用法

正文

httpcomponents-client

HttpComponents 也就是以前的httpclient项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端/服务器编程工具包,并且它支持 HTTP 协议最新的版本和建议。

HttpComponents项目下的HttpClient是为扩展而设计的,同时提供了对基本HTTP协议的强大支持,对于构建HTTP感知的客户端应用程序(例如Web浏览器,Web服务客户端或利用或扩展HTTP协议进行分布式通信的系统)

httpcomponents-client特点

  • 基于标准的纯Java,HTTP版本1.0和1.1的实现
  • 在可扩展的OO框架中完全实现所有HTTP方法(GET,POST,PUT,DELETE,HEAD,OPTIONS和TRACE)。
  • 支持使用HTTPS(基于SSL的HTTP)协议进行加密。
  • 通过HTTP代理的透明连接。
  • 通过CONNECT方法通过HTTP代理建立的隧道HTTPS连接。
  • Basic, Digest,NTLMv1,NTLMv2,NTLM2会话,SNPNEGO,Kerberos身份验证方案。
  • 自定义身份验证方案的插件机制。
  • 可插拔的安全套接字工厂,使使用第三方解决方案更加容易
  • 支持在多线程应用程序中使用的连接管理。支持设置最大总连接数以及每个主机的最大连接数。检测并关闭陈旧的连接。
  • 自动Cookie处理
  • 自定义Cookie策略的插件机制。
  • 请求输出流,以避免通过直接流到服务器的套接字来缓冲任何内容主体。
  • 响应输入流通过直接从套接字流传输到服务器来有效地读取响应主体。
  • 在HTTP / 1.0中使用KeepAlive的持久连接以及在HTTP / 1.1中的持久性
  • 直接访问服务器发送的响应代码和header。
  • 设置连接超时的能力。
  • 支持HTTP / 1.1响应缓存。

springboot与httpcomponents-client整合例子

这边提供一个httpcomponents-client工具类

1、pom.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>

2、创建httpcomponents-client配置类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Configuration
@ConfigurationProperties(prefix = "httpclient")
@Data
public class HttpClientConfig {

    private Integer maxTotal;

    private Integer defaultMaxPerRoute;
    private Integer connectTimeout;

    private Integer connectionRequestTimeout;

    private Integer socketTimeout;

    /**
     * HttpClient连接池
     * @return
     */
    @Bean
    public HttpClientConnectionManager httpClientConnectionManager() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(maxTotal);
        connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
        return connectionManager;
    }

    /**
     * 创建RequestConfig
     * @return
     */
    @Bean
    public RequestConfig requestConfig() {
        return RequestConfig.custom().setConnectTimeout(connectTimeout)
            .setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout)
            .build();
    }

    /**
     * 创建HttpClient
     * @param manager
     * @param config
     * @return
     */
    @Bean
    public CloseableHttpClient httpClient(HttpClientConnectionManager manager, RequestConfig config) {
        return HttpClientBuilder.create().setConnectionManager(manager).setDefaultRequestConfig(config)
            .build();
    }
}

3、httpcomponents-client工具类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
@Slf4j
public class HttpClientUtil {

    @Autowired
    private CloseableHttpClient httpClient;

    public  String doGet(String url, Map<String, String> param,Map<String,String> headers) {

        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            builder.setCharset(Charset.forName("utf-8"));
            URI uri = builder.build();

            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);
            if(headers!= null && !headers.isEmpty()){
                headers.forEach((name,value)->httpGet.setHeader(name,value));
            }

            // 执行请求
            response = httpClient.execute(httpGet);
           return EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                close(response);
                httpClient.close();
            } catch (IOException e) {
               log.error("doGet url:"+url+" fail,cause :"+e.getMessage(),e);
            }
        }
        return resultString;
    }

    public  String doGet(String url) {
        return doGet(url, null,null);
    }

    public  String doPost(String url, Map<String, String> param,Map<String,String> headers) {
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,Charset.forName("UTF-8"));
                httpPost.setEntity(entity);
            }

            if(headers!= null && !headers.isEmpty()){
                headers.forEach((name,value)->httpPost.setHeader(name,value));
            }

            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            log.error("doPost url:"+url+" fail,cause :"+e.getMessage(),e);
        } finally {
            close(response);
        }

        return resultString;
    }

    private void close(CloseableHttpResponse response) {
        try {
            if(response != null){
                response.close();
            }
        } catch (IOException e) {
         log.error(e.getMessage(),e);
        }
    }

    public  String doPost(String url) {
        return doPost(url, null,null);
    }

    public  String doPostJson(String url, String json) {
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建请求内容
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            log.error("doJson url:"+url+" fail,cause :"+e.getMessage(),e);
        } finally {
            close(response);
        }

        return resultString;
    }
}

ps:这个工具类是取自博主海恋北斗星的博文--HttpClientUtil-工具类,其链接如下

https://blog.csdn.net/zy12306/article/details/88554663

我在其工具类的基础上补充了header传值以及表单提交中文产生乱码问题修复,并注入spring

小结

这边没有对httpcomponents-client的方法进行描述,主要是因为httpcomponents-client属于工具类范畴,具体使用可以参考我这边提供的工具类实现就可以,开箱即用。如果想对httpcomponents-client进一步了解,可以访问如下链接

http://hc.apache.org/httpcomponents-client-ga/

restTemplate

spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接,大大提高客户端的编写效率。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。

springboot与restTemplate整合例子

这边提供一个restTemplate工具类

1、pom.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2、创建restTemplate配置类

RestTemplate默认依赖JDK提供的HttpURLConnection,如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。我这边就是使用 Apache HttpComponents,其核心配置如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Bean
    public ClientHttpRequestFactory requestFactory(CloseableHttpClient httpClient) {
        return new HttpComponentsClientHttpRequestFactory(httpClient);
    }

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory) {
        RestTemplate template = new RestTemplate(requestFactory);

        List<HttpMessageConverter<?>> list = template.getMessageConverters();
        for (HttpMessageConverter<?> mc : list) {
            if (mc instanceof StringHttpMessageConverter) {
                ((StringHttpMessageConverter) mc).setDefaultCharset(Charset.forName("UTF-8"));
            }
        }
        return template;
    }

3、restTemplate工具类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class RestTemplateUtil {

    @Autowired
    private  RestTemplate restTemplate;



    // ----------------------------------GET-------------------------------------------------------

    /**
     * GET请求调用方式
     *
     * @param url 请求URL
     * @param responseType 返回对象类型
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> get(String url, Class<T> responseType) {
        return restTemplate.getForEntity(url, responseType);
    }

    /**
     * GET请求调用方式
     *
     * @param url 请求URL
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> get(String url, Class<T> responseType, Object... uriVariables) {
        return restTemplate.getForEntity(url, responseType, uriVariables);
    }

    /**
     * GET请求调用方式
     *
     * @param url 请求URL
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> get(String url, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.getForEntity(url, responseType, uriVariables);
    }

    /**
     * 带请求头的GET请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> get(String url, Map<String, String> headers, Class<T> responseType, Object... uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return get(url, httpHeaders, responseType, uriVariables);
    }

    /**
     * 带请求头的GET请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> get(String url, HttpHeaders headers, Class<T> responseType, Object... uriVariables) {
        HttpEntity<?> requestEntity = new HttpEntity<>(headers);
        return exchange(url, HttpMethod.GET, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的GET请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> get(String url, Map<String, String> headers, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return get(url, httpHeaders, responseType, uriVariables);
    }

    /**
     * 带请求头的GET请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> get(String url, HttpHeaders headers, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<?> requestEntity = new HttpEntity<>(headers);
        return exchange(url, HttpMethod.GET, requestEntity, responseType, uriVariables);
    }

    // ----------------------------------POST-------------------------------------------------------

    /**
     * POST请求调用方式
     *
     * @param url 请求URL
     * @param responseType 返回对象类型
     * @return
     */
    public  <T> ResponseEntity<T> post(String url, Class<T> responseType) {
        return restTemplate.postForEntity(url, HttpEntity.EMPTY, responseType);
    }

    /**
     * POST请求调用方式
     *
     * @param url 请求URL
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType) {
        return restTemplate.postForEntity(url, requestBody, responseType);
    }

    /**
     * POST请求调用方式
     *
     * @param url 请求URL
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType, Object... uriVariables) {
        return restTemplate.postForEntity(url, requestBody, responseType, uriVariables);
    }

    /**
     * POST请求调用方式
     *
     * @param url 请求URL
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.postForEntity(url, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的POST请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> post(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return post(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的POST请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> post(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return post(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的POST请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> post(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return post(url, httpHeaders, requestBody, responseType, uriVariables);
    }
    /**

     * 带请求头的POST请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> post(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return post(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的POST请求调用方式
     *
     * @param url 请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> post(String url, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) {
        return restTemplate.exchange(url, HttpMethod.POST, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的POST请求调用方式
     *
     * @param url 请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> post(String url, HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.exchange(url, HttpMethod.POST, requestEntity, responseType, uriVariables);
    }

    // ----------------------------------PUT-------------------------------------------------------

    /**
     * PUT请求调用方式
     *
     * @param url 请求URL
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> put(String url, Class<T> responseType, Object... uriVariables) {
        return put(url, HttpEntity.EMPTY, responseType, uriVariables);
    }

    /**
     * PUT请求调用方式
     *
     * @param url 请求URL
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> put(String url, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody);
        return put(url, requestEntity, responseType, uriVariables);
    }

    /**
     * PUT请求调用方式
     *
     * @param url 请求URL
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> put(String url, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody);
        return put(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的PUT请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> put(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return put(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的PUT请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> put(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return put(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的PUT请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> put(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return put(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的PUT请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> put(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return put(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的PUT请求调用方式
     *
     * @param url 请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> put(String url, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) {
        return restTemplate.exchange(url, HttpMethod.PUT, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的PUT请求调用方式
     *
     * @param url 请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> put(String url, HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.exchange(url, HttpMethod.PUT, requestEntity, responseType, uriVariables);
    }

    // ----------------------------------DELETE-------------------------------------------------------

    /**
     * DELETE请求调用方式
     *
     * @param url 请求URL
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, Class<T> responseType, Object... uriVariables) {
        return delete(url, HttpEntity.EMPTY, responseType, uriVariables);
    }

    /**
     * DELETE请求调用方式
     *
     * @param url 请求URL
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, Class<T> responseType, Map<String, ?> uriVariables) {
        return delete(url, HttpEntity.EMPTY, responseType, uriVariables);
    }

    /**
     * DELETE请求调用方式
     *
     * @param url 请求URL
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * DELETE请求调用方式
     *
     * @param url 请求URL
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, Map<String, String> headers, Class<T> responseType, Object... uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return delete(url, httpHeaders, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, HttpHeaders headers, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(headers);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, Map<String, String> headers, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return delete(url, httpHeaders, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, HttpHeaders headers, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(headers);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return delete(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return delete(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url 请求URL
     * @param headers 请求头参数
     * @param requestBody 请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的DELETE请求调用方式
     *
     * @param url 请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) {
        return restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的DELETE请求调用方式
     *
     * @param url 请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> delete(String url, HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, responseType, uriVariables);
    }

    // ----------------------------------通用方法-------------------------------------------------------

    /**
     * 通用调用方式
     *
     * @param url 请求URL
     * @param method 请求方法类型
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) {
        return restTemplate.exchange(url, method, requestEntity, responseType, uriVariables);
    }

    /**
     * 通用调用方式
     *
     * @param url 请求URL
     * @param method 请求方法类型
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public  <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.exchange(url, method, requestEntity, responseType, uriVariables);
    }
}

ps:该工具类取自博主诚信天下博文--Spring 远程调用工具类RestTemplateUtils,其链接如下

https://www.cnblogs.com/jonban/p/rest.html

该工具类就是对restTmplate进行浅浅的封装一层,因为restTemplate的http远程调用,基本上也是一两句代码,如果对restemplate的相关API感兴趣的朋友,可以查看如下链接

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

webclient

webClient是一个响应式客户端,它提供了restTemplate的替代方法。它公开了一个功能齐全、流畅的api,并依赖于非阻塞I / O,使其能够比restTemplate更高效地支持高并发性。webclient非常适合流式的传输方案,并且依赖于较低级别的HTTP客户端库来执行请求,是可插拔的。

webclient特点

  • 非阻塞,Reactive的,并支持更高的并发性和更少的硬件资源。
  • 提供利用Java 8 lambdas的函数API。
  • 支持同步和异步方案。
  • 支持从服务器向上或向下流式传输。

springboot与webclient整合

这边提供一个webclient工具类

1、pom.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

2、webclient工具类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class WebClientUtil {

    private  final MediaType MEDIATYPE_JSON = MediaType.APPLICATION_JSON_UTF8;

    private  final MediaType MEDIATYPE_FORM = MediaType.APPLICATION_FORM_URLENCODED;

    @Autowired
    private WebClient webClient;

    /**
     *
     * @param paramter
     *            请求参数
     * @param url
     *            请求路径
     * @param resultType
     *            返回结果类型
     * @return
     */
    public  <T> T post(Object paramter, String url, Class<T> resultType) {

        return post(uri(url, HttpMethod.POST), paramter, resultType);
    }

    /**
     *
     * @param paramter
     *            请求参数
     * @param url
     *            请求路径
     * @param header
     *            请求头
     * @param resultType
     *            返回结果类型
     * @return
     */
    public  <T> T post(Object paramter, String url, Map<String, String> header, Class<T> resultType) {

        RequestBodySpec uri = uri(url, HttpMethod.POST);
        addHeader(header, uri);
        return post(uri, paramter, resultType);
    }

    private  <T> T post(RequestBodySpec uri, Object paramter, Class<T> resultType) {

        return uri.contentType(MEDIATYPE_JSON).body(Mono.just(paramter), Object.class).retrieve().bodyToMono(resultType)
                .block();
    }

    /**
     *
     * @param paramter
     *            请求参数
     * @param url
     *            请求路径
     * @param header
     *            请求头
     * @param resultType
     *            返回结果类型
     * @return
     */
    public  <T> T postForm(Map<String,String> paramter, String url, Map<String, String> header, Class<T> resultType) {
        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
        formData.setAll(paramter);
        RequestBodySpec uri = uri(url, HttpMethod.POST);
        addHeader(header, uri);
        return postForm(uri, formData, resultType);
    }

    private  <T> T postForm(RequestBodySpec uri, MultiValueMap<String, String> formData , Class<T> resultType) {

        return uri.contentType(MEDIATYPE_FORM).body(BodyInserters.fromFormData(formData)).retrieve().bodyToMono(resultType)
                .block();
    }

    /**
     *
     * @param url
     *            请求路径
     * @param resultType
     *            返回结果类型
     * @return
     */
    public  <T> T get(String url, Class<T> resultType) {

        return uri(url, HttpMethod.GET).retrieve().bodyToMono(resultType).block();
    }

    /**
     *
     * @param url
     *            请求路径
     * @param header
     *            请求头
     * @param resultType
     *            返回结果类型
     * @return
     */
    public  <T> T get(String url, Map<String, String> header, Class<T> resultType) {

        RequestBodySpec uri = uri(url, HttpMethod.GET);
        addHeader(header, uri);
        return uri.retrieve().bodyToMono(resultType).block();
    }

    private  RequestBodySpec uri(String url, HttpMethod method) {

        return webClient.method(method).uri(url);
    }

    private  void addHeader(Map<String, String> header, RequestBodySpec uri) {

        if (!CollectionUtils.isEmpty(header)) {
            header.forEach((name, value) -> uri.cookie(name, value));
        }
    }

}

ps:该工具类取自博主lkw风满楼博文springboot2.0 webClient api调用,其链接如下

https://blog.csdn.net/lkw411526/article/details/79766686

该工具同样也是对webclient进行浅浅的封装一层,因为webclient的http远程调用也是一两句代码。然后该工具原先的博主并没有提供表单提交的实现,我对其进行补充。如果对webclient感兴趣的朋友,可以查看如下链接

https://docs.spring.io/spring/docs/5.1.2.RELEASE/spring-framework-reference/web-reactive.html#webflux-client

以及

https://josdem.io/techtalk/spring/springbootwebclient/

小结

上面提供的工具类,基本上可以满足日常的http远程调用的需求了。下边就再介绍一下,我对这三种工具类进行再次封装实现http调用

自己封装的轮子

1、在启动类上,加上EnableHttpClients注解

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@SpringBootApplication(scanBasePackages = "com.github.lybgeek")
@EnableHttpClients(basePackages = "com.github.lybgeek")
public class HttpClientApplication
{
    public static void main( String[] args )
    {

        SpringApplication.run(HttpClientApplication.class,args);
    }
}

2、编写一个业务服务接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Remote(url = "http://localhost:8080/api/1.0.0/book",headers = {@RemoteHeader(name = "AccessToken",value = "123456")})
public interface BookService {

  @RemoteRequestMapping(path = "/add")
  BookDTO addBook(BookDTO bookDTO);

  @RemoteRequestMapping(path = "/update",type = HttpclientTypeEnum.REST_TEMPLATE)
  BookDTO editBook(BookDTO bookDTO);

  @RemoteRequestMapping(path = "/del/{id}",type = HttpclientTypeEnum.WEB_CLIENT)
  boolean delBookById(@RemotePathParam(value = "id") Long id);

  @RemoteRequestMapping(path = "/page")
  PageResult<BookDTO> pageBook(PageQuery<BookDTO> pageQuery);

  @RemoteRequestMapping(path = "/list")
  List<BookDTO> listBooks(BookDTO bookDTO);

}

上边的注解,如果使用过springboot开发的朋友,正常都会知道啥意思。这边介绍一下@RemoteRequestMapping中的type,这个type可以用来指定是要使用httpcomponents-client、restTemplate、webClient中的其中一种

3、编写单元测试

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@ @Autowired
    private BookService bookService;


    @Test
    public void testAddBook(){
        for(int i = 1; i <= 10; i++){
            BookDTO bookDTO = BookDTO.builder().bookName("python从入门到精通(第"+i+")版")
                    .author("张三"+i).description("python从入门到精通(第"+i+")版,热门系列").price(BigDecimal.valueOf(i*10)).stock(i).build();
            bookDTO = bookService.addBook(bookDTO);
            System.out.println(bookDTO);
        }
    }

    @Test
    public void testUpdateBook(){
        BookDTO bookDTO = BookDTO.builder().id(1L).bookName("图解Http").author("大神").description("http入门系列教程").price(BigDecimal.valueOf(23.2)).stock(1).build();
        bookDTO =  bookService.editBook(bookDTO);
        System.out.println(bookDTO);
    }

    @Test
    public void testDelBook(){
        boolean del = bookService.delBookById(10L);
        Assert.assertTrue(del);
    }

    @Test
    public void testPageBook(){
        PageQuery pageQuery = new PageQuery<>().setPageNo(1).setPageSize(5);
        BookDTO bookDTO = new BookDTO();
        bookDTO.setAuthor("张三");
        //   bookDTO.setBookName("图解Http");
        //   bookDTO.setId(4L);
        pageQuery.setQueryParams(bookDTO);

        PageResult<BookDTO> pageResult = bookService.pageBook(pageQuery);

        if(pageResult != null){
            pageResult.getList().forEach(book -> System.out.println(book));
        }

    }


    @Test
    public void testListBook(){
        BookDTO bookDTO = new BookDTO();
        bookDTO.setAuthor("张三");
        bookDTO.setBookName("java");
        //       bookDTO.setId(5L);
        List<BookDTO> bookDTOS = bookService.listBooks(bookDTO);
        bookDTOS.forEach(book-> System.out.println(book));
    }






}

总结

http客户端的java版调用除了上述的几种,还有很多其他,比如feign等,其次本文的轮子,是以表单提交的方式的调用http,而非采用数据转json再调用。

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-httpclient

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linyb极客之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
蓝桥ROS机器人之现代C++学习笔记4.3 元组
学习程序如下: #include <tuple> #include <iostream> #include <variant> auto get_student(int id) { if (id == 0) return std::make_tuple(3.8, 'A', "John"); if (id == 1) return std::make_tuple(2.9, 'C', "Jack"); if (id == 2) retur
zhangrelay
2022/04/29
2740
蓝桥ROS机器人之现代C++学习笔记4.3 元组
链表和C++ std::list详解
链表是一种在物理上非连续、非顺序的数据结构,数据元素的逻辑顺序是通过链表中的指针链接实现,其由若干节点所组成。std::list是C++中支持常数时间从容器任何位置插入和移除元素的容器,但其不支持快速的随机访问,其通常实现为双向链表。
艰默
2023/09/05
1.6K0
链表和C++ std::list详解
C++17常用新特性(十一)---折叠表达式
从C++17开始,可以使用二元操作符对形参包中的参数进行计算,这一特性主要针对可变参数模板进行提升。支持的二元操作符多达32个。例如,下面的函数将会返回传入的所有的参数的和。
CPP开发前沿
2022/06/04
1.6K0
多态实现-虚函数、函数指针以及变体
作为一名C++面试官,问的最多的问题就是说说多态的实现机制,无非想听到的答案就是虚函数以及虚函数表,也算是烂大街的问题了,稍微有点经验的候选人都会答上个一二三。今天,借助本文,我们聊聊实现多态的几个方式。
高性能架构探索
2022/08/25
9740
多态实现-虚函数、函数指针以及变体
C++那些事之玩转optional
本节将会引入5个版本的optional实现,最终揭秘C++ STL optional实现,最后给出一个小项目作为练习的例子,让大家感受step by step学习的乐趣,所有代码、答案与相关参考资料,已更新于知识星球,欢迎大家加入学习。
公众号guangcity
2023/09/02
4000
C++那些事之玩转optional
C++ 动态新闻推送 第7期
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。
王很水
2021/08/31
4720
C++ 动态新闻推送 第19期
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。
王很水
2021/08/31
3770
【C++11】 改进我们的设计模式---访问者模式
访问者模式的应用场景不多,它可以在不改变类成员的前提下定义作用于这些元素的新的操作,是一种数据元素和数据操作分离的设计模式。
CPP开发前沿
2021/11/16
4620
【C++11】 改进我们的设计模式---访问者模式
整理C/C++的可变参数
c语言中使用可变参数最熟悉应该就是printf, 其是通过...来从代码语句中表示可变化的参数表。
Rock_Lee
2020/09/21
5.6K0
C++ std::optional完全解读
在编写可选择接受或返回对象的函数的时候,通常的做法是选择一个单独的布尔值来确保函数入参或者返回对象的可用性:
艰默
2023/10/24
1.2K0
C++ std::optional完全解读
全面盘点17个C++17的高级特性
C++17是目前比较常用的版本之一,今天花时间来梳理一下17个重要特性,所有的特性也不止这么点。
公众号guangcity
2024/03/22
3.6K0
全面盘点17个C++17的高级特性
双端队列和C++ std::deque详解
双端队列实际上是队列的一种变形,队列要求只能在队尾添加元素,在队头删除元素,而双端队列在队头和队尾都可以进行添加和删除元素的操作。双端队列是限定插入和删除操作在表的两端进行的线性表。C++中提供deque容器来实现双端队列的功能。
艰默
2023/09/05
6940
双端队列和C++ std::deque详解
C++ 中文周刊 第121期
RSS https://github.com/wanghenshui/cppweeklynews/releases.atom
王很水
2024/07/30
1130
C++ 中文周刊 第121期
C++17 New Features
如果说 C++11 和 C++20 是两个改动大、影响比较深远的"大版本",那么我感觉 C++17 算是一个小版本。(推荐 vs2019,gcc8,clang10,支持 C++17)
JIFF
2020/06/09
1.1K0
C++ 动态新闻推送 第32期
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态
王很水
2021/10/13
4630
C++17常用新特性(九)---扩展的using声明
从C++17开始,using声明语句被扩展了,声明多个标识符时可以在一行进行声明,用逗号分隔即可。如下面的代码所示:
CPP开发前沿
2022/04/13
1K0
C++17常用新特性(九)---扩展的using声明
C++反射深入浅出 - 1. ponder 反射实现分析总篇
给静态语言添加动态特性, 似乎是C++社区一件大家乐见其成的事情, 轮子也非常多, 我们不一一列举前辈们造的各种流派的轮子了, 主要还是结合我们框架用到的C++反射实现, 结合C++的新特性, 来系统的拆解目前框架中的反射实现. 另外代码最早脱胎于Ponder, 整体处理流程基本与原版一致, 所以相关的源码可以直接参考 ponder的原始代码 . 文章计划分分7篇: - [[1. c++反射深入浅出 - ponder 反射实现分析总篇]] - [[2. c++反射深入浅出 - property实现分析]] - [[3. c++反射深入浅出 - function实现分析]] - [[4. c++反射深入浅出 - 基于反射的Lua中间层实现]] - [[5. C++反射深入浅出 - 反射信息的自动生成]] - [[6. C++反射深入浅出 - 反射的其他应用]] - [[7. C++反射深入浅出 - c++20 concept 改造]]
fangfang
2022/04/01
1.3K0
C++反射深入浅出 - 1. ponder 反射实现分析总篇
现代C++教程:高速上手(四)-容器
std::array与std::vector不同的是,array对象的大小是固定的,如果容器大小是固定的,那么可以优先考虑使用std::array容器。
程序员小涛
2020/12/03
8610
C++17 std::variant 详解:概念、用法和实现细节
在C++的发展历程中,C++17带来了许多实用的新特性,其中std::variant尤为引人注目。它本质上是一种类型安全的联合体,能够在同一时刻持有多种可能类型中的某一个值。这种特性为开发者提供了极大的便利,在面对需要处理多种不同类型数据的场景时,std::variant提供了一种灵活且高效的解决方案,使得代码编写更加简洁、安全。
码事漫谈
2025/01/27
920
C++17 std::variant 详解:概念、用法和实现细节
C++ 动态新闻推送 第4期
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。
王很水
2021/08/31
6240
推荐阅读
相关推荐
蓝桥ROS机器人之现代C++学习笔记4.3 元组
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验