2021-09-07 SpringBoot应用发起http请求 - yahya

Http客户端(发起http请求)

在Java的世界中,Http客户端之前一直是Apache家的HttpClient占据主导,但是由于此包较为庞大,API又比较难用,因此并不使用很多场景。而新兴的OkHttp、Jodd-http固然好用,但是面对一些场景时,学习成本还是有一些的。很多时候,我们想追求轻量级的Http客户端,并且追求简单易用。而JDK自带的HttpUrlConnection可以满足大部分需求。

总结,http客户端有几种:

  1. JDK自带的HttpURLConnection
  2. Apache HttpComponents
  3. OkHttp
  4. Jodd-http

RestTemplate

RestTemplate只对其他的HTTP客户端进行了封装,本身并没有实现HTTP相关的基础功能。其底层实现是可以配置切换的。

HttpAccessor

RestTemplate有一个非常重要的类叫做HttpAccessor,可以理解为HTTP的基础类
在这里插入图片描述从源码中我们可以看出:

  • RestTemplate 支持至少三种HTTP客户端库。
    • SimpleClientHttpRequestFactory。对应的HTTP库是java JDK自带的HttpURLConnection。
    • HttpComponentsAsyncClientHttpRequestFactory。对应的HTTP库是Apache HttpComponents。
    • OkHttp3ClientHttpRequestFactory。对应的HTTP库是OkHttp
  • java JDK自带的HttpURLConnection是默认的底层HTTP实现客户端
  • SimpleClientHttpRequestFactory,即java JDK自带的HttpURLConnection不支持HTTP协议的Patch方法,如果希望使用Patch方法,需要将底层HTTP客户端实现切换为Apache HttpComponents 或 OkHttp
  • 可以通过设置setRequestFactory方法,来切换RestTemplate的底层HTTP客户端实现类库。

底层实现切换方法

OkHttp 优于 Apache HttpComponents、Apache HttpComponents优于HttpURLConnection,可切换为okHTTP。

  1. 切换为okHTTP

首先引入okHTTP的依赖

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.7.2</version>
</dependency>

如果是spring 环境下通过如下方式使用OkHttp3ClientHttpRequestFactory初始化RestTemplate bean对象。

@Configuration
public class ContextConfig {
    @Bean("OKHttp3")
    public RestTemplate OKHttp3RestTemplate(){
        RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory());
        return restTemplate;
    }
}

如果是非Spring环境,直接new RestTemplate(new OkHttp3ClientHttpRequestFactory())之后使用就可以了。

  1. 切换为Apache HttpComponents

引入依赖:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.12</version>
</dependency>

使用HttpComponentsClientHttpRequestFactory初始化RestTemplate bean对象

@Bean("httpClient")
public RestTemplate httpClientRestTemplate(){
    RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
    return restTemplate;
}

如果是非Spring环境,直接new RestTemplate(new HttpComponentsClientHttpRequestFactory())之后使用就可以了。

配置RestTemplate访问细节,例如访问超时、get请求支持body数据

@EnableConfigurationProperties(value = {HttpClientProperties.class})
@Configuration
public class RestTemplateConfig {

    @Autowired
@Lazy
    private HttpClientProperties httpClientProperties;

    @Bean
    public RestTemplate restTemplate1() {
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory1());
        return restTemplate;
    }

    @Bean
    public ClientHttpRequestFactory httpRequestFactory1() {
        return new HttpComponentsClientHttpRequestCRMFactory(httpClient1());
    }

    @Bean
    public HttpClient httpClient1() {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        HttpClientProperties.PoolProperties poolProperties = this.httpClientProperties.getPool();
        connectionManager.setMaxTotal(poolProperties.getMaxTotal());
        connectionManager.setDefaultMaxPerRoute(poolProperties.getDefaultMaxPerRoute());
        connectionManager.setValidateAfterInactivity(poolProperties.getValidateAfterInactivity());
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(httpClientProperties.getSocketTimeout()) //服务器返回数据(response)的时间,超过抛出read timeout
                .setConnectTimeout(httpClientProperties.getConnectTimeout()) //连接上服务器(握手成功)的时间,超出抛出connect timeout
                .setConnectionRequestTimeout(httpClientProperties.getConnectionRequestTimeout())//从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
                .build();
        return HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();
    }

    /**
     * 支持GET请求发送BODY
     */
    private static class HttpComponentsClientHttpRequestCRMFactory extends HttpComponentsClientHttpRequestFactory {
        public HttpComponentsClientHttpRequestCRMFactory(HttpClient httpClient) {
            super(httpClient);
        }

        @Override
        protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {
            if (httpMethod == HttpMethod.GET) {
                return new HttpGetRequestForBody(uri);
            }
            return super.createHttpUriRequest(httpMethod, uri);
        }
    }

    private static class HttpGetRequestForBody extends HttpEntityEnclosingRequestBase {
        public HttpGetRequestForBody(final URI uri) {
            super.setURI(uri);
        }

        @Override
        public String getMethod() {
            return HttpMethod.GET.name();
        }
    }
}

RestTemplate类中的方法

发起请求

Hutool-http(HttpUtil)

Hutool针对Http请求做了一层封装,基于JDK的HttpUrlConnection封装完成,完整支持https、代理、文件上传、Cookie记忆。
Hutool-http的核心集中在两个类:HttpRequest、HttpResponse,针对大部分情境,封装了HttpUtil工具类。

HttpUtil

HttpRequest

HttpResponse

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值