HttpUtils.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. package top.lvzhiqiang.util;
  2. import com.alibaba.fastjson.JSONException;
  3. import com.alibaba.fastjson.JSONObject;
  4. import org.apache.http.HttpResponse;
  5. import org.apache.http.HttpStatus;
  6. import org.apache.http.NameValuePair;
  7. import org.apache.http.client.config.RequestConfig;
  8. import org.apache.http.client.entity.UrlEncodedFormEntity;
  9. import org.apache.http.client.methods.*;
  10. import org.apache.http.client.utils.URIBuilder;
  11. import org.apache.http.client.utils.URLEncodedUtils;
  12. import org.apache.http.conn.ConnectionKeepAliveStrategy;
  13. import org.apache.http.impl.client.CloseableHttpClient;
  14. import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
  15. import org.apache.http.impl.client.HttpClients;
  16. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
  17. import org.apache.http.message.BasicNameValuePair;
  18. import org.apache.http.protocol.HttpContext;
  19. import org.apache.http.util.EntityUtils;
  20. import org.slf4j.Logger;
  21. import org.slf4j.LoggerFactory;
  22. import java.io.IOException;
  23. import java.io.UnsupportedEncodingException;
  24. import java.net.URISyntaxException;
  25. import java.util.*;
  26. /**
  27. * HTTP工具类
  28. *
  29. * @author shiyong
  30. * 2019-12-17 16:08
  31. */
  32. public class HttpUtils {
  33. // 编码格式。发送编码格式统一用UTF-8
  34. private static final String ENCODING = "UTF-8";
  35. // 设置连接超时时间,单位毫秒。ConnectTimeoutException
  36. private static final int CONNECT_TIMEOUT = 60000;
  37. // 请求获取数据的超时时间(即响应时间),单位毫秒。如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。SocketTimeoutException
  38. private static final int SOCKET_TIMEOUT = 30000;
  39. // 设置从connect Manager获取Connection 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。ConnectionPoolTimeout
  40. private static final int CONNECTION_REQUEST_TIMEOUT = 60000;
  41. private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
  42. private static CloseableHttpClient httpClient = null;
  43. /**
  44. * 自己构建httpclient连接池。通过享元模式来解决该问题来解决HttpClient引起的TCP连接数高问题
  45. *
  46. * @return
  47. */
  48. public static synchronized CloseableHttpClient getHttpClient() {
  49. if (httpClient == null) {
  50. PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
  51. // 连接池最大连接数,默认为20
  52. cm.setMaxTotal(2000);
  53. // 单条链路最大连接数(一个ip+一个端口是一个链路),即每个主机的最大连接数,默认为2
  54. cm.setDefaultMaxPerRoute(1000);
  55. ConnectionKeepAliveStrategy kaStrategy = new DefaultConnectionKeepAliveStrategy() {
  56. @Override
  57. public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
  58. long keepAlive = super.getKeepAliveDuration(response, context);
  59. if (keepAlive == -1) {
  60. keepAlive = 60000;
  61. }
  62. return keepAlive;
  63. }
  64. };
  65. httpClient = HttpClients.custom().setConnectionManager(cm).setKeepAliveStrategy(kaStrategy).build();
  66. }
  67. return httpClient;
  68. }
  69. /**
  70. * 发送get请求,返回字符串
  71. *
  72. * @param url 请求地址
  73. * @return java.lang.String
  74. * @author shiyong
  75. * 2020/4/15 10:54
  76. */
  77. public static String doGetToStr(String url) throws IOException, URISyntaxException {
  78. return doGetToStr(url, new HashMap<>());
  79. }
  80. /**
  81. * 发送get请求,返回字符串
  82. *
  83. * @param url 请求地址
  84. * @param params 请求参数
  85. * @return java.lang.String
  86. * @author shiyong
  87. * 2020/4/15 10:58
  88. */
  89. public static String doGetToStr(String url, Map<String, String> params) throws IOException, URISyntaxException {
  90. return doGetToStr(url, new HashMap<>(), params);
  91. }
  92. /**
  93. * 发送get请求,返回字符串
  94. *
  95. * @param url 请求地址
  96. * @param headers 请求头
  97. * @param params 请求参数
  98. * @return java.lang.String
  99. * @author shiyong
  100. * 2020/4/15 10:59
  101. */
  102. public static String doGetToStr(String url, Map<String, String> headers, Map<String, String> params) throws IOException, URISyntaxException {
  103. // 创建httpClient对象
  104. // CloseableHttpClient httpClient = HttpClients.createDefault();
  105. CloseableHttpClient httpClient = getHttpClient();
  106. // 创建httpResponse对象
  107. CloseableHttpResponse httpResponse = null;
  108. HttpGet httpGet = null;
  109. try {
  110. // 创建访问的地址
  111. URIBuilder uriBuilder = new URIBuilder(url);
  112. if (params != null) {
  113. Set<Map.Entry<String, String>> entrySet = params.entrySet();
  114. for (Map.Entry<String, String> entry : entrySet) {
  115. uriBuilder.setParameter(entry.getKey(), entry.getValue());
  116. }
  117. }
  118. // 创建http对象
  119. httpGet = new HttpGet(uriBuilder.build());
  120. RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
  121. httpGet.setConfig(requestConfig);
  122. // 设置请求头
  123. packageHeader(headers, httpGet);
  124. // 执行请求
  125. httpResponse = httpClient.execute(httpGet);
  126. if (null == httpResponse || null == httpResponse.getStatusLine() || null == httpResponse.getEntity() || httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
  127. return "";
  128. }
  129. return EntityUtils.toString(httpResponse.getEntity(), ENCODING);
  130. } catch (JSONException e) {
  131. throw new JSONException(e.getMessage());
  132. } catch (IOException e) {
  133. throw new IOException(e);
  134. } finally {
  135. // 释放资源
  136. if (httpGet != null) {
  137. httpGet.abort();
  138. httpGet.releaseConnection();
  139. }
  140. release(httpResponse, httpClient);
  141. }
  142. }
  143. /**
  144. * 发送post请求,返回字符串
  145. *
  146. * @param url 请求地址
  147. * @param headers 请求头
  148. * @param params 请求参数
  149. * @return java.lang.String
  150. * @author shiyong
  151. * 2020/4/15 11:35
  152. */
  153. public static String doPostToStr(String url, Map<String, String> headers, Map<String, String> params) throws IOException, JSONException {
  154. // 创建httpClient对象
  155. // CloseableHttpClient httpClient = HttpClients.createDefault();
  156. CloseableHttpClient httpClient = getHttpClient();
  157. // 创建httpResponse对象
  158. CloseableHttpResponse httpResponse = null;
  159. HttpPost httpPost = null;
  160. try {
  161. // 创建http对象
  162. httpPost = new HttpPost(url);
  163. RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
  164. httpPost.setConfig(requestConfig);
  165. //httpPost.setHeader(HttpHeaders.CONNECTION, "close");
  166. packageHeader(headers, httpPost);
  167. // 封装请求参数
  168. packageParam(params, httpPost);
  169. // 执行请求
  170. httpResponse = httpClient.execute(httpPost);
  171. if (null == httpResponse || null == httpResponse.getStatusLine() || null == httpResponse.getEntity() || httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
  172. return "";
  173. }
  174. return EntityUtils.toString(httpResponse.getEntity(), ENCODING);
  175. } catch (JSONException e) {
  176. throw new JSONException(e.getMessage());
  177. } catch (IOException e) {
  178. throw new IOException(e);
  179. } finally {
  180. // 释放资源
  181. if (httpPost != null) {
  182. httpPost.abort();
  183. httpPost.releaseConnection();
  184. }
  185. release(httpResponse, httpClient);
  186. }
  187. }
  188. /**
  189. * 发送post请求,返回JSONObject
  190. *
  191. * @param url 请求地址
  192. * @param params 参数集合
  193. * @return com.alibaba.fastjson.JSONObject
  194. * @author shiyong
  195. * 2019/11/23 18:39
  196. */
  197. public static JSONObject doPost(String url, Map<String, String> params) throws IOException {
  198. return doPost(url, new HashMap<String, String>(), params);
  199. }
  200. /**
  201. * 发送post请求,返回JSONObject
  202. *
  203. * @param url 请求地址
  204. * @param headers 请求头
  205. * @param params 请求参数
  206. * @return com.alibaba.fastjson.JSONObject
  207. * @author shiyong
  208. * 2019/11/23 18:35
  209. */
  210. public static JSONObject doPost(String url, Map<String, String> headers, Map<String, String> params) throws IOException {
  211. String content = doPostToStr(url, headers, params);
  212. if (StringUtils.isEmpty(content)) {
  213. return new JSONObject();
  214. }
  215. return JSONObject.parseObject(content);
  216. }
  217. /**
  218. * 封装请求头
  219. *
  220. * @param params 请求头
  221. * @param httpMethod 请求方式
  222. * @author shiyong
  223. * 2019/11/23 19:21
  224. */
  225. private static void packageHeader(Map<String, String> params, HttpRequestBase httpMethod) {
  226. if (params != null) {
  227. Set<Map.Entry<String, String>> entrySet = params.entrySet();
  228. for (Map.Entry<String, String> entry : entrySet) {
  229. // 设置到请求头到HttpRequestBase对象中
  230. httpMethod.setHeader(entry.getKey(), entry.getValue());
  231. }
  232. }
  233. }
  234. /**
  235. * 封装请求参数
  236. *
  237. * @param params 请求参数
  238. * @param httpMethod 请求方式
  239. * @author shiyong
  240. * 2019/11/23 19:22
  241. */
  242. private static void packageParam(Map<String, String> params, HttpEntityEnclosingRequestBase httpMethod) throws UnsupportedEncodingException {
  243. if (params != null) {
  244. List<NameValuePair> nvps = new ArrayList<>();
  245. Set<Map.Entry<String, String>> entrySet = params.entrySet();
  246. for (Map.Entry<String, String> entry : entrySet) {
  247. nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
  248. }
  249. UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, ENCODING);
  250. formEntity.setContentType(URLEncodedUtils.CONTENT_TYPE);
  251. // 设置到请求的http对象中
  252. httpMethod.setEntity(formEntity);
  253. }
  254. }
  255. /**
  256. * 释放资源
  257. *
  258. * @param httpResponse HTTP响应
  259. * @param httpClient HTTP客户端
  260. * @author shiyong
  261. * 2019/11/23 19:28
  262. */
  263. private static void release(CloseableHttpResponse httpResponse, CloseableHttpClient httpClient) {
  264. try {
  265. if (httpResponse != null) {
  266. httpResponse.close();
  267. }
  268. // 连接池使用的时候不能关闭连接,否则下次使用会抛异常 java.lang.IllegalStateException: Connection pool shut down
  269. // 选择使用连接池,就是将连接全部交由连接池管理,而我们在程序中使用了httpClient.close()就破坏了这以规则
  270. /*if (httpClient != null) {
  271. httpClient.close();
  272. }*/
  273. } catch (IOException e) {
  274. log.error("释放HTTP请求资源失败!", e);
  275. }
  276. }
  277. }