springboot使用RestTemplate+httpclient连接池发送http消息
简介
- RestTemplate是spring支持的一个请求http rest服务的模板对象,性质上有点像jdbcTemplate
- RestTemplate底层还是使用的httpclient(org.apache.http.client.HttpClient)发送请求的
- HttpClient可以做连接池,而发送消息的工具类可以使用RestTemplate,所以如果你的项目需求http连接池,RestTemplate+httpclient连接池是一种不错的方式,可以节省开发工作,也可以更优雅的使用。
配置
- maven依赖
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.6</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
- Java配置类
package com.jinjian.rt.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "http-pool") @Data public class HttpPoolProperties { private Integer maxTotal; private Integer defaultMaxPerRoute; private Integer connectTimeout; private Integer connectionRequestTimeout; private Integer socketTimeout; private Integer validateAfterInactivity; }
package com.jinjian.rt.config; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { @Autowired private HttpPoolProperties httpPoolProperties; @Bean public RestTemplate restTemplate() { return new RestTemplate(httpRequestFactory()); } @Bean public ClientHttpRequestFactory httpRequestFactory() { return new HttpComponentsClientHttpRequestFactory(httpClient()); } @Bean public HttpClient httpClient() { Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", SSLConnectionSocketFactory.getSocketFactory()) .build(); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); connectionManager.setMaxTotal(httpPoolProperties.getMaxTotal()); connectionManager.setDefaultMaxPerRoute(httpPoolProperties.getDefaultMaxPerRoute()); connectionManager.setValidateAfterInactivity(httpPoolProperties.getValidateAfterInactivity()); RequestConfig requestConfig = RequestConfig.custom() .setSocketTimeout(httpPoolProperties.getSocketTimeout()) //服务器返回数据(response)的时间,超过抛出read timeout .setConnectTimeout(httpPoolProperties.getConnectTimeout()) //连接上服务器(握手成功)的时间,超出抛出connect timeout .setConnectionRequestTimeout(httpPoolProperties.getConnectionRequestTimeout())//从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool .build(); return HttpClientBuilder.create() .setDefaultRequestConfig(requestConfig) .setConnectionManager(connectionManager) .build(); } }
-
使用方法
package com.jinjian.rt.service; import com.jinjian.rt.dto.RuiooResponseEntity; import org.json.JSONException; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.io.IOException; @Service public class TestService { @Autowired private RestTemplate restTemplate; public void startTest() throws JSONException, IOException { JSONObject jsonObject = new JSONObject(); jsonObject.put("first","jinjian"); jsonObject.put("second","aaaaaaa"); long start = System.currentTimeMillis(); //{1} 表示第一个占位符,也可以填写name,但是这是另一个getForEntity重载方法 //RuiooResponseEntity 为自定义dto ResponseEntity<RuiooResponseEntity> entity = restTemplate.getForEntity("http://39.107.104.221/api/test/{1}", RuiooResponseEntity.class, 123); long end = System.currentTimeMillis(); long cost = end - start; System.out.println("耗时:"+cost); RuiooResponseEntity body = entity.getBody(); body.getData(); body.getStatus(); body.getMessage(); System.out.println("响应体:"+ body); } }