发布时间:2023-05-27 19:30
前言:最近项目中用到了httpclient,于是乎去学习了一下,但是在实操过程中发现存在很多的问题,踩了很多坑,所以便想着记录下来,以便自己回顾,同时也希望能够帮助有需要的朋友们。
1.HttpClient介绍:
要是不了解咱去就问下百度:HttpClient
2.为什么要用到HttpClient
httpclient的使用范围很广泛,不过在我的知识储备中主要是以下两点:
3.原因
在项目开发中,需要调用另外一个项目的接口,然鹅这个项目不是微服务的系统,用不了SpringCloud的Fegin,,然后再加上知识有限,于是就想到了使用HttpClient.
4.遇到的问题
开始使用的过程中,没啥问题一路通畅,感觉如鱼得水般,后来发现自己太年轻,然后就遇见了一系列的问题:
5.解决问题
常规操作,导入依赖、yml配置、注入spring
org.apache.httpcomponents
httpclient
4.5.8
#httpclient自定义属性
http:
maxTotal: 100 #最大连接数
defaultMaxPerRoute: 50 #并发数
connectTimeout: 1000 #创建连接的最长时间
connectionRequestTimeout: 1000 #从连接池中获取到连接的最长时间
socketTimeout: 1000 #数据传输的最长时间
staleConnectionCheckEnabled: true #提交请求前测试连接是否可用
配置配,然后注入spring
@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();
}
}
然后就是根据具体的业务操作抽取出一个工具类来,这里我就不贴出来了。接着该解决问题了~
如果你使用的是Post请求,那么有一点一定要注意,那就是数据格式
//JSON格式
post.setHeader(\"Content-Type\", \"application/json;charset=utf8\");
//普通form表单
post.setHeader(\"Content-Type\", \"x-www-form-urlencoded\");
//带文件对象的from表单
post.setHeader(\"Content-Type\", \"multipart/form-data\");
//除了在头部设置,也可以在参数对象里面设置
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
参数为对象的请求(JSON)
public HttpResult doPostJSON(String url, Object object, String reqHeader) throws Exception {
// 声明httpPost请求
HttpPost post = new HttpPost(url);
// 加入配置信息
post.setConfig(config);
post.setHeader(\"Content-Type\", \"application/json;charset=utf8\");
post.setHeader(\"User-Agent\", reqHeader);
String result = null;
HttpResponse resp = null;
try {
//将object转成StringEntity并且设置UTF-8格式
StringEntity param = new StringEntity(JSONObject.toJSONString(object),\"UTF-8\");
post.setEntity(param);
//执行请求
resp = this.httpClient.execute(post);
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 返回json格式:
result = JSONObject.toJSONString(EntityUtils.toString(resp.getEntity()));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return new HttpResult(resp.getStatusLine().getStatusCode(),result);
}
参数为Map的请求(JSON)
public HttpResult doPost(String url, Map<String,Object> map,String reqHeader) throws Exception {
// 声明httpPost请求
HttpPost post = new HttpPost(url);
// 加入配置信息
post.setConfig(config);
post.setHeader(\"User-Agent\", reqHeader);
String result = null;
HttpResponse resp = null;
try {
//设置参数
List<NameValuePair> list = new ArrayList<NameValuePair>();
Iterator iterator = map.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String,String> elem = (Map.Entry<String, String>) iterator.next();
list.add(new BasicNameValuePair(elem.getKey(),String.valueOf(elem.getValue())));
}
if(list.size() > 0){
//将集合封装成UrlEncodedFormEntity设置字符格式
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,\"UTF-8\");
post.setEntity(entity);
}
//执行请求
resp = this.httpClient.execute(post);
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 返回json格式:
result = JSONObject.toJSONString(EntityUtils.toString(resp.getEntity()));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return new HttpResult(resp.getStatusLine().getStatusCode(),result);
}
上传文件
public HttpResult doPostForm(String url, MultipartFile file, Map<String,Object> map,String reqHeader) throws Exception {
// 声明httpPost请求
HttpPost post = new HttpPost(url);
// 加入配置信息
post.setConfig(config);
post.setHeader(\"User-Agent\",reqHeader );
String result = null;
HttpResponse resp = null;
try {
MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE).setCharset(Consts.UTF_8);
//要上传的文件,以文件流的形式进行传输
builder.addBinaryBody(\"file\",file.getInputStream(), ContentType.MULTIPART_FORM_DATA, file.getOriginalFilename());
//content-type
ContentType strContent=ContentType.create(\"text/plain\", Charset.forName(\"UTF-8\"));
Iterator iterator = map.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String,String> elem = (Map.Entry<String, String>) iterator.next();
builder.addTextBody(elem.getKey(), elem.getValue(),strContent);
}
HttpEntity entity = builder.build();
post.setEntity(entity);
//执行请求
resp = this.httpClient.execute(post);
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 返回json格式:
result = JSONObject.toJSONString(EntityUtils.toString(resp.getEntity()));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return new HttpResult(resp.getStatusLine().getStatusCode(),result);
}
那么说到这里问题也差不多解决了,以上就是本人使用httpClient的简单经历,让我们一起沉浸在bug的海洋里,无法自拔吧~
PS:如有错误或者不正确的地方还请多多指教,一起共同学习共同进步