spring boot整合httpClient
配置类
package com.qq.demo.WebConfig;
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;
@Configuration
public class HttpClientConfig {
//用value注解获取properties中的值
@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;
/**
* 定义httpClient连接池
* @return
*/
@Bean(name = "httpClientConnectionManager")
public PoolingHttpClientConnectionManager getHttpClientConnectionManager() {
PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager();
//最大连接数
httpClientConnectionManager.setMaxTotal(maxTotal);
//并发数
httpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
return httpClientConnectionManager;
}
/**定义 HttpClient工厂,这里使用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
*/
@Bean
public CloseableHttpClient getCloseableHttpClient(
@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder) {
return httpClientBuilder.build();
}
/** 定义requestConfig的工厂
* 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")注入bean
@Qualifier("builder") RequestConfig.Builder builder) {
return builder.build();
}
}
控制层
service层
package com.qq.demo.controller;
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 org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class HttpClientService {
@Autowired(required=false)
private CloseableHttpClient httpClient;
@Autowired(required=false)
private RequestConfig requestConfig;
/**
* 编辑httpget请求(请求路径是拼接而成)
* 1.使用map<k(id),v(值)>,保存传递的参数
* 2.指定uri
* 3.设置字符集编码
*/
public String doGet(String uri,Map<String,String> params,String charset){
String result=null;
//1.判断字符集是否为空,如空,则设置字符集
if(StringUtils.isEmpty(charset)){
charset="utf-8";
}
//2.判断是否有参数,有,则拼接参数路径
try {
if(params!=null){
//使用URIBuilder进行请求路径拼接
URIBuilder builder=new URIBuilder(uri);
for (Map.Entry<String, String> entry: params.entrySet()) {
builder.addParameter(entry.getKey(), entry.getValue());
}
//动态拼接(build()生成新的请求路径)
uri=builder.build().toString();
}
System.out.println("动态拼接的路径---->"+uri);
//3.定义请求对象
HttpGet httpGet=new HttpGet(uri);
//4.定义请求的链接时长
httpGet.setConfig(requestConfig);
CloseableHttpResponse closeableHttpResponse= httpClient.execute(httpGet);
//5.判断请求是否正确
if(closeableHttpResponse.getStatusLine().getStatusCode()==200){
result=EntityUtils.toString(
closeableHttpResponse.getEntity(),
charset);
}
} catch (Exception e) {
e.printStackTrace();
}
//6.返回
// System.out.println("comment包httpClientService类中:"+result);
return result;
}
public String doGet(String uri,Map<String,String> params){
return doGet(uri,params,null);
}
public String doGet(String uri){
return doGet(uri,null);
}
/*POST提交方式
* 难点:参数如何封装httpClient提供表单提交的对象
* 将数据封装到表单中即可
*/
public String doPost(String uri,Map<String, String> params,String charset){
String result=null;
//判断字符集是否为空,为空则赋编码集
if(StringUtils.isEmpty(charset)){
charset="utf-8";
}
//创建请求对象
HttpPost httpPost=new HttpPost(uri);
//定义超时时长
httpPost.setConfig(requestConfig);
try {
//判断参数是否为空
if(params!=null){
List<NameValuePair> parameters=new ArrayList<>();
//遍历map集合,给list赋值
for (Map.Entry<String, String> enyry : params.entrySet()) {
//NameValuePair的实现类
BasicNameValuePair basicNameValuePair=
new BasicNameValuePair(enyry.getKey(),enyry.getValue());
//放入list集合
parameters.add(basicNameValuePair);
}
//封装from表单
UrlEncodedFormEntity formEntity=
new UrlEncodedFormEntity(parameters, charset);
//将请求的实体对象,封装到POST对象中
httpPost.setEntity(formEntity);
}
//发送请求
CloseableHttpResponse httpResponse=httpClient.execute(httpPost);
//判断是否成功
if(httpResponse.getStatusLine().getStatusCode()==200){
result=EntityUtils.toString(
httpResponse.getEntity(),charset);
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public String doPost(String uri){
return doPost(uri,null);
}
public String doPost(String uri,
Map<String, String> params){
return doPost(uri, params, null);
}
}
关闭连接的类
package com.qq.demo.WebConfig;
import org.apache.http.conn.HttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
*定期清理无效的连接
*/
@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();
}
}
}
结果
最后再来个过滤器配置,用于检测页面报错,快速定位问题