正式参加工作一年了,记录一下开发接口使用的Http工具类
依赖引入:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
<optional>true</optional>
</dependency>
package com.google.common.utils;
import com.alibaba.fastjson.JSONObject;
import com.google.common.constants.CharSetConstants;
import lombok.extern.slf4j.Slf4j;
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.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Http请求工具类
*
* @author wk
* update time 20190815 14:00
*/
@Slf4j
public class HttpRequestUtils {
private static final Charset CHARSET_UTF8 = Charset.forName(CharSetConstants.UTF_8);
private static final Charset CHARSET_GBK = Charset.forName(CharSetConstants.GBK);
private static PoolingHttpClientConnectionManager cm = null;
static {
LayeredConnectionSocketFactory sslsf = null;
try {
sslsf = new SSLConnectionSocketFactory(createIgnoreVerifySSL());
} catch (NoSuchAlgorithmException e) {
log.error("创建SSL连接失败");
e.printStackTrace();
} catch (KeyManagementException e) {
log.error("创建SSL连接失败");
e.printStackTrace();
}
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", sslsf)
.register("http", new PlainConnectionSocketFactory())
.build();
cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
}
private static CloseableHttpClient getHttpClient() {
return HttpClients.custom().setConnectionManager(cm).build();
}
/**
* 绕过证书方式实现ssl请求
*
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
SSLContext sc = SSLContext.getInstance("SSLv3");
// 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
X509TrustManager trustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
String paramString) throws CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
String paramString) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sc.init(null, new TrustManager[]{trustManager}, null);
return sc;
}
/**
* 判断字符集
*
* @param charsetFlag
* @return
*/
private static Charset judgeCharSet(String charsetFlag) {
if (CharSetConstants.UTF_8.equals(charsetFlag)) {
return CHARSET_UTF8;
} else if (CharSetConstants.GBK.equals(charsetFlag)) {
return CHARSET_GBK;
}
return null;
}
/**
* @param timeout 设置从connect Manager获取Connection 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。
* @param connectTimeout 设置连接超时时间,单位毫秒。
* @param socketTimeout 请求获取数据的超时时间,单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。
* @return
*/
private static RequestConfig getRequestConfig(int timeout, int connectTimeout, int socketTimeout) {
return RequestConfig.custom()
.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(timeout)
.setSocketTimeout(socketTimeout).build();
}
/**
* 关闭流
*
* @param res
*/
private static void closeStream(CloseableHttpResponse res) {
if (res != null) {
try {
EntityUtils.consume(res.getEntity());
res.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* return HttpResult
*
* @param httpResponse
* @param charset
* @return
* @throws IOException
*/
private static HttpResult getHttpResult(CloseableHttpResponse httpResponse, Charset charset) throws IOException {
int statusCode = httpResponse.getStatusLine().getStatusCode();
if (httpResponse.getEntity() != null) {
return new HttpResult(statusCode,
EntityUtils.toString(httpResponse.getEntity(), charset));
} else {
return new HttpResult(statusCode, "");
}
}
/**
* 无参get请求
*
* @param url
* @return
*/
public static HttpResult doGet(String url, JSONObject jsonData) {
CloseableHttpClient closeableHttpClient = HttpRequestUtils.getHttpClient();
CloseableHttpResponse httpResponse = null;
try {
String params = "";
if (jsonData != null && !jsonData.isEmpty()) {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
Set<Map.Entry<String, Object>> set = jsonData.entrySet();
for (Map.Entry<String, Object> entry : set) {
String key = entry.getKey();
String value = entry.getValue().toString();
nameValuePairs.add(new BasicNameValuePair(key, value));
}
params = EntityUtils.toString(new UrlEncodedFormEntity(nameValuePairs, CHARSET_GBK));
}
HttpGet get = new HttpGet(url + params);
get.setConfig(getRequestConfig(5000, 5000, 20000));
httpResponse = closeableHttpClient.execute(get);
return getHttpResult(httpResponse, CHARSET_UTF8);
} catch (IOException e) {
log.error("httpclient请求失败", e);
e.printStackTrace();
return null;
} finally {
closeStream(httpResponse);
}
}
/**
* doGetSSL请求
*
* @param url
* @param jsonData
* @return
*/
public static HttpResult doGetSSL(String url, JSONObject jsonData) {
CloseableHttpResponse httpResponse = null;
CloseableHttpClient httpClient = getHttpClient();
try {
String params = "";
if (jsonData != null && !jsonData.isEmpty()) {
List<NameValuePair> nameValuePairs = new ArrayList<>();
Set<Map.Entry<String, Object>> set = jsonData.entrySet();
for (Map.Entry<String, Object> entry : set) {
String key = entry.getKey();
String value = entry.getValue().toString();
nameValuePairs.add(new BasicNameValuePair(key, value));
}
params = EntityUtils.toString(new UrlEncodedFormEntity(nameValuePairs, CharSetConstants.UTF_8));
}
url = url + "?" + params;
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(getRequestConfig(5000, 5000, 20000));
httpResponse = httpClient.execute(httpGet);
return getHttpResult(httpResponse, CHARSET_UTF8);
} catch (IOException e) {
log.error("httpclient请求失败", e);
e.printStackTrace();
return null;
} finally {
closeStream(httpResponse);
}
}
/**
* 参数为字符串比如json串
*
* @param url
* @param str
* @param charsetFlag
* @return
*/
public static HttpResult doPost(String url, String str, String charsetFlag) {
CloseableHttpClient httpClient = HttpRequestUtils.getHttpClient();
CloseableHttpResponse httpResponse = null;
Charset charset = judgeCharSet(charsetFlag);
try {
HttpPost post = new HttpPost(url);
StringEntity se = new StringEntity(str, charset);
post.setEntity(se);
httpResponse = httpClient.execute(post);
return getHttpResult(httpResponse, charset);
} catch (IOException e) {
log.error("httpclient请求失败", e);
e.printStackTrace();
return null;
} finally {
closeStream(httpResponse);
}
}
/**
* doPost请求,参数UrlEncodedFormEntity
*
* @param url
* @param map
* @return
*/
public static HttpResult doPost(String url, Map<String, Object> map) {
CloseableHttpResponse httpResponse = null;
try {
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
if (map != null) {
List<NameValuePair> params = new ArrayList<>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
}
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, CHARSET_UTF8);
httpPost.setConfig(getRequestConfig(5000, 5000, 20000));
httpPost.setEntity(formEntity);
}
httpResponse = closeableHttpClient.execute(httpPost);
return getHttpResult(httpResponse, CHARSET_UTF8);
} catch (Exception e) {
log.error("httpclient请求失败", e);
e.printStackTrace();
return null;
} finally {
closeStream(httpResponse);
}
}
/**
* JSONObject json
*
* @param url
* @param str
* @return
*/
public static HttpResult doPost(String url, String str) {
CloseableHttpClient httpClient = HttpRequestUtils.getHttpClient();
CloseableHttpResponse httpResponse = null;
try {
HttpPost post = new HttpPost(url);
StringEntity stringEntity = new StringEntity(str, ContentType.create("application/xml", CharSetConstants.UTF_8));
post.setEntity(stringEntity);
post.setConfig(getRequestConfig(5000, 5000, 20000));
httpResponse = httpClient.execute(post);
return getHttpResult(httpResponse, CHARSET_UTF8);
} catch (IOException e) {
log.error("httpclient请求失败", e);
} finally {
closeStream(httpResponse);
}
return null;
}
public static HttpResult doPost(String url, JSONObject json) {
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
CloseableHttpResponse httpResponse = null;
HttpPost post = new HttpPost(url);
try {
String data = json.toString();
StringEntity stringEntity = new StringEntity(data, ContentType.create("text/plain", CharSetConstants.UTF_8));
post.setEntity(stringEntity);
post.setConfig(getRequestConfig(5000, 5000, 20000));
httpResponse = closeableHttpClient.execute(post);
return getHttpResult(httpResponse, CHARSET_UTF8);
} catch (Exception e) {
log.error("httpclient请求失败", e);
e.printStackTrace();
return null;
} finally {
closeStream(httpResponse);
}
}
public static HttpResult soapPost(String url, String str) {
CloseableHttpClient httpClient = HttpRequestUtils.getHttpClient();
CloseableHttpResponse httpResponse = null;
try {
HttpPost post = new HttpPost(url);
StringEntity stringEntity = new StringEntity(str, ContentType.create("text/xml", CharSetConstants.UTF_8));
post.setEntity(stringEntity);
post.setConfig(getRequestConfig(5000, 5000, 20000));
httpResponse = httpClient.execute(post);
return getHttpResult(httpResponse, CHARSET_UTF8);
} catch (IOException e) {
log.error("httpclient请求失败", e);
e.printStackTrace();
return null;
} finally {
closeStream(httpResponse);
}
}
}
/**
* @author wk
*/
public class HttpResult {
/**
* 响应的状态码
*/
private int code;
/**
* 响应的响应体
*/
private String body;
public HttpResult(int statusCode, String string) {
this.code = statusCode;
this.body = string;
}
public HttpResult() {
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
package com.google.common.constants;
/**
* @author wk
* @Description:
* @date 2019/8/13 17:37
**/
public class CharSetConstants {
public static final String UTF_8 = "UTF-8";
public static final String GBK = "GBK";
}
public static CloseableHttpClient createSSLClientDefault() {
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
//信任所有
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
//该方法已过时(依然可以使用),改用上述方式实现SSL请求
SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(sslContext,SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
return HttpClients.custom().setSSLSocketFactory(sslFactory).build();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
return HttpClients.createDefault();
}
工作中遇到的问题:
1.乱码问题,在使用StringEntity这个类时,StringEntity(String string, String charset) 用到了这个构造方法,但是传入的utf-8时,通过debug发现,传递的参数依然乱码。询问大佬后,说是这个方法是有bug的,必须这样写
new StringEntity(data, ContentType.create("application/json", "utf-8"));
2.连续请求一个接口,报错Exception in thread "main" java.lang.IllegalStateException: Connection pool shut down
把这块代码删除就好了
if (closeableHttpClient != null) {
try {
closeableHttpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
3.(http工具类没有加closeStream这个方法,目前还没有进行验证是否是这个原因)
netstat -ano|find /i /c "TIME_WAIT"
生产服务器(windows),服务报这个错误,导致服务卡顿,甚至崩溃,所有的http请求均失败。
No buffer space available (maximum connections reached?): connectNo buffer space available (maximum connections reached?): connect
4.java.net.SocketException: Connection reset
请求银行接口(测试环境),经常报这个错误,在本地运行服务很少报这个错,没找出原因,也可能是Tomcat配置的问题
参照链接:
https://www.cnblogs.com/chinaifae/articles/10443047.html