1.首先加入httpclient需要的jar包
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.3.1</version> </dependency>
2.在配置文件中加入httpclient需要的一些配置参数
#最大连接数 http.maxTotal = 100 #并发数 http.defaultMaxPerRoute = 20 #创建连接的最长时间 http.connectTimeout=1000 #从连接池中获取到连接的最长时间 http.connectionRequestTimeout=500 #数据传输的最长时间 http.socketTimeout=10000 #提交请求前测试连接是否可用 http.staleConnectionCheckEnabled=true
3.注入连接池等,用于在service层获取httpclient
@Configuration public class HttpClient { @Value("${http.maxTotal}") private Integer maxTotal; @Value("${http.defaultMaxPerRoute}") private Integer defaultMaxPerRoute; @Value("${http.connectTimeout}") private Integer connectTimeout; @Value("${http.connectionRequestTimeout}") private Integer connectionRequestTimeout; @Value("${http.socketTimeout}") private Integer socketTimeout; @Value("${http.staleConnectionCheckEnabled}") private boolean staleConnectionCheckEnabled; /** * 首先实例化一个连接池管理器,设置最大连接数、并发连接数 * @return */ @Bean(name = "httpClientConnectionManager") public PoolingHttpClientConnectionManager getHttpClientConnectionManager(){ PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager(); //最大连接数 httpClientConnectionManager.setMaxTotal(maxTotal); //并发数 httpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute); return httpClientConnectionManager; } /** * 实例化连接池,设置连接池管理器。 * 这里需要以参数形式注入上面实例化的连接池管理器 * @param httpClientConnectionManager * @return */ @Bean(name = "httpClientBuilder") public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager")PoolingHttpClientConnectionManager httpClientConnectionManager){ //HttpClientBuilder中的构造方法被protected修饰,所以这里不能直接使用new来实例化一个HttpClientBuilder,可以使用HttpClientBuilder提供的静态方法create()来获取HttpClientBuilder对象 HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); httpClientBuilder.setConnectionManager(httpClientConnectionManager); return httpClientBuilder; } /** * 注入连接池,用于获取httpClient * @param httpClientBuilder * @return */ @Bean public CloseableHttpClient getCloseableHttpClient(@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder){ return httpClientBuilder.build(); } /** * Builder是RequestConfig的一个内部类 * 通过RequestConfig的custom方法来获取到一个Builder对象 * 设置builder的连接信息 * 这里还可以设置proxy,cookieSpec等属性。有需要的话可以在此设置 * @return */ @Bean(name = "builder") public RequestConfig.Builder getBuilder(){ RequestConfig.Builder builder = RequestConfig.custom(); return builder.setConnectTimeout(connectTimeout) .setConnectionRequestTimeout(connectionRequestTimeout) .setSocketTimeout(socketTimeout) .setStaleConnectionCheckEnabled(staleConnectionCheckEnabled); } /** * 使用builder构建一个RequestConfig对象 * @param builder * @return */ @Bean public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder){ return builder.build(); } }
4.编写一个案例Controller层
@RestController public class HttpClientController { @Resource private HttpAPIService httpAPIService; @RequestMapping("httpclient") public String test() throws Exception { String str = httpAPIService.doGet("http://www.baidu.com"); System.out.println(str); return "hello"; } }
5.service层
@Service public class HttpAPIService { @Autowired private CloseableHttpClient httpClient; @Autowired private RequestConfig config; /** * 不带参数的get请求,如果状态码为200,则返回body,如果不为200,则返回null * * @param url * @return * @throws Exception */ public String doGet(String url) throws Exception { // 声明 http get 请求 HttpGet httpGet = new HttpGet(url); // 装载配置信息 httpGet.setConfig(config); // 发起请求 CloseableHttpResponse response = this.httpClient.execute(httpGet); // 判断状态码是否为200 if (response.getStatusLine().getStatusCode() == 200) { // 返回响应体的内容 return EntityUtils.toString(response.getEntity(), "UTF-8"); } return null; } /** * 带参数的get请求,如果状态码为200,则返回body,如果不为200,则返回null * * @param url * @return * @throws Exception */ public String doGet(String url, Map<String, Object> map) throws Exception { URIBuilder uriBuilder = new URIBuilder(url); if (map != null) { // 遍历map,拼接请求参数 for (Map.Entry<String, Object> entry : map.entrySet()) { uriBuilder.setParameter(entry.getKey(), entry.getValue().toString()); } } // 调用不带参数的get请求 return this.doGet(uriBuilder.build().toString()); } /** * 带参数的post请求 * * @param url * @param map * @return * @throws Exception */ public HttpResult doPost(String url, Map<String, Object> map) throws Exception { // 声明httpPost请求 HttpPost httpPost = new HttpPost(url); // 加入配置信息 httpPost.setConfig(config); // 判断map是否为空,不为空则进行遍历,封装from表单对象 if (map != null) { List<NameValuePair> list = new ArrayList<NameValuePair>(); for (Map.Entry<String, Object> entry : map.entrySet()) { list.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString())); } // 构造from表单对象 UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(list, "UTF-8"); // 把表单放到post里 httpPost.setEntity(urlEncodedFormEntity); } // 发起请求 CloseableHttpResponse response = this.httpClient.execute(httpPost); return new HttpResult(response.getStatusLine().getStatusCode(), EntityUtils.toString( response.getEntity(), "UTF-8")); } /** * 不带参数post请求 * * @param url * @return * @throws Exception */ public HttpResult doPost(String url) throws Exception { return this.doPost(url, null); } }
6.处理关闭连接的线程
@Component public class IdleConnectionEvictor extends Thread { @Autowired private HttpClientConnectionManager connMgr; private volatile boolean shutdown; public IdleConnectionEvictor() { super(); super.start(); } @Override public void run() { try { while (!shutdown) { synchronized (this) { wait(5000); // 关闭失效的连接 connMgr.closeExpiredConnections(); } } } catch (InterruptedException ex) { // 结束 } } //关闭清理无效连接的线程 public void shutdown() { shutdown = true; synchronized (this) { notifyAll(); } } }