org.apache.httpcomponents
httpclient
4.3.1
#最大连接数
http.maxTotal = 100
#并发数
http.defaultMaxPerRoute = 20
#创建连接的最长时间
http.connectTimeout=2000
#从连接池中获取到连接的最长时间
http.connectionRequestTimeout=5000
#数据传输的最长时间
http.socketTimeout=10000
#提交请求前测试连接是否可用
http.staleConnectionCheckEnabled=true
package com.qishimai.mybatisplus.pojo;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*
* HttpClient工具类,注入连接池等,用在工具类获取httpclient
*
*
* @Author 王文龙
* @Date 2019-08-16 11:10
*/
@Configuration
public class HttpClientPool {
//最大连接数
@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 httpClientConnectionManager
*/
@Bean(name = "httpClientConnectionManager")
public PoolingHttpClientConnectionManager getHttpClientConnectionManager() {
PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager();
//最大连接数
httpClientConnectionManager.setMaxTotal(maxTotal);
//并发数
httpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
return httpClientConnectionManager;
}
/**
* 实例化连接池,设置连接池管理器
* 这里需要以参数形式注入上面实例化的连接池管理器
*
* @param httpClientConnectionManager 连接池管理器
* @return httpClientBuilder 连接池
*/
@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 获取httpclient
*/
@Bean
public CloseableHttpClient getCloseableHttpClient(@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder) {
return httpClientBuilder.build();
}
/**
* Builder是RequestConfig的一个内部类
* 通过RequestConfig的custom方法来获取到一个Builder对象
* 设置builder的连接信息
* 这里还可以设置proxy,cookieSpec等属性,有需要的话可以在此设置
*
* @return builder
*/
@Bean(name = "builder")
public RequestConfig.Builder getBuilder() {
RequestConfig.Builder builder = RequestConfig.custom();
//将属性 set进 builder 中
builder.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout)
.setSocketTimeout(socketTimeout)
.setStaleConnectionCheckEnabled(staleConnectionCheckEnabled);
return builder;
}
/**
* 使用builder构建一个RequestConfig对象
*
* @param builder 连接信息
* @return builder.build()
*/
@Bean
public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder) {
return builder.build();
}
}
package com.qishimai.mybatisplus.pojo;
import org.apache.http.conn.HttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
*
* 处理关闭连接的线程
*
*
* @Author 王文龙
* @Date 2019-08-16 14:14
*/
@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();
}
}
}
/**
* @Author 王文龙
* @Date 2019-07-03 11:57
*/
public class JsonResult {
private int code;//状态码
private String msg;//错误码
private T data;//相应具体的数据类型
//省略构造方法和 getting,setting 方法
}
package com.qishimai.mybatisplus.service.impl;
import com.qishimai.mybatisplus.utils.JsonResult;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
/**
*
* 设置http客户端 请求类型
*
*
* @Author 王文龙
* @Date 2019-08-16 11:44
*/
@Service
public class HttpClientApiUtils {
@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);
System.out.println(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请求
*
* @param url 请求路径
* @param map map 集合
* @return 响应内容
* @throws Exception 抛异常
*/
public String doGet(String url, Map map) throws Exception {
URIBuilder uriBuilder = new URIBuilder(url);
if (map != null) {
//遍历map,拼接请求参数
for (Map.Entry entry : map.entrySet()) {
uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
}
}
//调用不带参数get请求
return this.doGet(uriBuilder.build().toString());
}
/**
* 带参数的post请求
* @param url 请求路径
* @param map 入参
* @return *
* @throws IOException *
*/
public JsonResult doPost(String url, Map map) throws IOException {
//声明httpPost请求
HttpPost httpPost = new HttpPost(url);
//加入配置信息
httpPost.setConfig(config);
//判断map是否为空,不为空则进行遍历,封装from表单对象
if (map!=null){
ArrayList list = new ArrayList<>();
for (Map.Entry entry:map.entrySet()){
list.add(new BasicNameValuePair(entry.getKey(),entry.getValue().toString()));
}
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(list, "UTF-8");
// 把表单放到post里
httpPost.setEntity(urlEncodedFormEntity);
}
//发送请求
CloseableHttpResponse response = httpClient.execute(httpPost);
return new JsonResult<>(response.getStatusLine().getStatusCode(),"发送请求",EntityUtils.toString(response.getEntity(),"UTF-8"),0);
}
/**
* 不带参数的post请求
* @param url 请求路径
* @return *
* @throws IOException *
*/
public JsonResult doPost(String url) throws IOException {
return this.doPost(url,null);
}
}
@RestController
@RequestMapping("httpclient")
public class HttpClientController {
@Resource
private HttpClientApiUtils httpClientApiUtils;
//发送http请求
@RequestMapping("client")
public String test() throws Exception {
String s = httpClientApiUtils.doGet("http://www.baidu.com");
System.err.println(s);
return "hello";
}
}
注:浏览器,postman测试,返回hello就说明成功