已解决
基于httpclient依赖封装一个更适用自己业务场景的工具类
来自网友在路上 167867提问 提问时间:2023-10-25 04:41:39阅读次数: 67
最佳答案 问答题库678位专家为你答疑解惑
使用依赖
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.8.0</version></dependency>
工具类
public class HttpClientUtil {private static HttpClientUtil httpClient;private final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);private final PoolingHttpClientConnectionManager cm;private final RequestConfig reqConfig;private final HttpClientBuilder clientBuilder;//设置同时访问的线程private final Semaphore semaphore = new Semaphore(300);{ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", plainsf).register("https", sslsf).build();cm = new PoolingHttpClientConnectionManager(registry);cm.setMaxTotal(1000);cm.setDefaultMaxPerRoute(1000);//连接配置信息reqConfig = RequestConfig.custom().setConnectionRequestTimeout(15000).setConnectTimeout(15000).setSocketTimeout(15000).setExpectContinueEnabled(false).build();clientBuilder = HttpClients.custom();clientBuilder.setDefaultRequestConfig(reqConfig);clientBuilder.setConnectionManager(cm);}/*** 执行一个get类型的HTTP请求** @param url 需要访问的地址* @param headerMap headerMap可以为* @return 请求路径响应的内容*/public String getHttpResponseBody(String url, Map<String, String> headerMap) {try {semaphore.acquire();} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 恢复中断}HttpGet request = new HttpGet(url);return requestExecute(request, headerMap);}/*** 执行一个get类型的HTTP请求,返回输入流** @param url 需要访问的地址* @param headerMap headerMap可以为* @return 请求路径响应的内容*/public ByteArrayOutputStream getHttpResponseIs(String url, Map<String, String> headerMap) {try {semaphore.acquire();} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 恢复中断}HttpGet request = new HttpGet(url);return requestExecuteByte(request, headerMap);}/*** 执行一个post类型的HTTP请求** @param url 需要访问的地址* @param headerMap headerMap可以为* @param paramBody 请求参数体* @return 请求路径响应的内容*/public String postHttpResponseBody(String url, Map<String, String> headerMap, Object paramBody) {try {semaphore.acquire();} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 恢复中断}HttpPost request = new HttpPost(url);if (paramBody != null) {String bodyStr = JSON.toJSONString(paramBody);request.setEntity(new StringEntity(bodyStr, ContentType.APPLICATION_JSON));}return requestExecute(request, headerMap);}/*** 执行一个post类型的HTTP请求** @param url 需要访问的地址* @param headerMap headerMap可以为* @param paramBody 请求参数体* @return 请求路径响应的内容*/public String postHttpResponseXmlBody(String url, Map<String, String> headerMap, String paramBody) {try {semaphore.acquire();} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 恢复中断}HttpPost request = new HttpPost(url);if (paramBody != null) {request.setEntity(new StringEntity(paramBody, ContentType.APPLICATION_XML));}return requestExecute(request, headerMap);}/*** 执行一个put类型的HTTP请求** @param url 需要访问的地址* @param headerMap headerMap可以为* @param paramBody 请求参数体* @return 请求路径响应的内容*/public String putHttpResponseBody(String url, Map<String, String> headerMap, Object paramBody) {try {semaphore.acquire();} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 恢复中断}String bodyStr = JSON.toJSONString(paramBody);HttpPut request = new HttpPut(url);request.setEntity(new StringEntity(bodyStr, ContentType.APPLICATION_JSON));return requestExecute(request, headerMap);}/*** 执行一个post类型的HTTP请求,用于上传文件** @param url 请求路径* @param fileField 文件字段名字* @param bytes 文件* @param headerMap 请求头* @param paramBody 请求附带参数对象* @return 请求路径响应的内容*/public String postFileHttpResponseBody(String url, String fileField, byte[] bytes,Map<String, String> headerMap, Object paramBody) {headerMap.put("Content-Type", null);try {semaphore.acquire();} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 恢复中断}MultipartEntityBuilder builder = MultipartEntityBuilder.create().setCharset(StandardCharsets.UTF_8);JSONObject jsonObject = (JSONObject) JSON.toJSON(paramBody);if (bytes != null) {String filename = jsonObject.getString("filename");filename = filename == null ? "" : filename;ContentType contentType = ContentType.create("application/octet-stream", "UTF-8");builder.addBinaryBody(fileField, bytes, contentType, filename);}final ContentType contentType = ContentType.create("text/plain", "UTF-8");jsonObject.forEach((k, v) -> {if (v == null) return;StringBody stringBody = new StringBody(v.toString(), contentType);builder.addPart(k, stringBody);});HttpPost request = new HttpPost(url);request.setEntity(builder.build());return requestExecute(request, headerMap);}/*** 执行一个post类型的HTTP请求格式是application/x-www-form-urlencoded** @param url 需要访问的地址* @param headerMap headerMap可以为* @param params 请求参数* @return 请求路径响应的内容*/public String postHttpFormResponseBody(String url, Map<String, String> headerMap, Object params) {try {semaphore.acquire();} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 恢复中断}ArrayList<BasicNameValuePair> basicNameValuePairs = new ArrayList<>();if (params instanceof Map) {Set<Map.Entry<String, String>> entries = ((Map) params).entrySet();for (Map.Entry<String, String> entry : entries) {basicNameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));}} else {ReflectionUtils.doWithFields(params.getClass(), field -> {field.setAccessible(true);Object val = field.get(params);if (val != null) {basicNameValuePairs.add(new BasicNameValuePair(field.getName(), val.toString()));}});}UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(basicNameValuePairs, StandardCharsets.UTF_8);HttpPost request = new HttpPost(url);request.setEntity(urlEncodedFormEntity);headerMap.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");return requestExecute(request, headerMap);}/*** 组装get请求的参数到API路径中** @param reqParam API的请求参数对象,由{@link ApiBaseReq.BaseBuilder#build()}生成* @return 组装后的路径 https://ad.e.kuaishou.com/rest/openapi/v1/comment/list?nick=zym&age=25&pid=6666*/public String createGetRequestUrl(ApiBaseReq reqParam, String platform) {String apiUrl = reqParam.getApiUrl();JSONObject json = (JSONObject) JSONObject.toJSON(reqParam);return this.createGetRequestUrl(json, apiUrl, platform);}/*** 组装get请求的参数到API路径中** @param reqJson API的请求参数Json* @param apiUrl 暂未拼接的路径例如:https://ad.e.kuaishou.com/rest/openapi/v1/comment/list* @return 组装后的路径 https://ad.e.kuaishou.com/rest/openapi/v1/comment/list?nick=zym&age=25&pid=6666*/public String createGetRequestUrl(JSONObject reqJson, String apiUrl, String platform) {String params = reqJson.entrySet().stream().filter(x -> x.getValue() != null && !"null".equals(x.getValue())).map(x -> {try {return this.joinParam(x.getKey(), x.getValue(), platform);} catch (UnsupportedEncodingException e) {logger.error("createGetRequestUrl UnsupportedEncodingException:", e);return null;}}).collect(Collectors.joining("&"));//如果结尾不是?并且包含=,则说明url已经拼接过参数了if (!apiUrl.endsWith("?") && apiUrl.contains("=")) return apiUrl + "&" + params;return apiUrl.endsWith("?") ? apiUrl + params : apiUrl + "?" + params;}private String joinParam(Object key, Object val, String platform) throws UnsupportedEncodingException {if (val instanceof JSONArray) {if ("BL_BL".equalsIgnoreCase(platform)) {// 把 '[' 或 ']' 全部替换为空串return key + "=" + val.toString().replaceAll("\\[|\\]|\"", "");}return key + "=" + URLEncoder.encode(val.toString(), "utf-8");} else if (val instanceof JSONObject) {return key + "=" + URLEncoder.encode(val.toString(), "utf-8");} else {return key + "=" + val;}}/*** 真正开始执行HTTP请求** @param request 请求内容* @param headerMap 请求头部* @return 请求响应的内容*/private String requestExecute(HttpRequestBase request, Map<String, String> headerMap) {setHeaders(request, headerMap);//请求头部设置CloseableHttpClient httpClient = clientBuilder.build();HttpClientContext localContext = HttpClientContext.create();CloseableHttpResponse httpResp = null;//执行try {httpResp = httpClient.execute(request, localContext);if (httpResp == null) {logger.error("【requestExecute】请求失败 httpResp is null");return null;}int statusCode = httpResp.getStatusLine().getStatusCode();//请求状态码200位成功if (httpResp.getStatusLine().getStatusCode() != 200) {logger.error("【requestExecute】请求失败 statusCode:{}", statusCode);return null;}if (httpResp.getEntity() == null) return null;return getResponseStr(httpResp);} catch (Exception e) {logger.error("【httpClient】 requestExecute Exception:{}", e.getMessage());return null;} finally {StreamClose.close(httpResp);request.releaseConnection();clientClose();}}/*** 真正开始执行HTTP请求,返回输入流** @param request 请求内容* @param headerMap 请求头部* @return 请求响应的内容*/private ByteArrayOutputStream requestExecuteByte(HttpRequestBase request, Map<String, String> headerMap) {setHeaders(request, headerMap);//请求头部设置CloseableHttpClient httpClient = clientBuilder.build();HttpClientContext localContext = HttpClientContext.create();CloseableHttpResponse httpResp = null;//执行try {httpResp = httpClient.execute(request, localContext);if (httpResp == null) {logger.error("【requestExecuteByte】请求失败 httpResp is null");return null;}int statusCode = httpResp.getStatusLine().getStatusCode();//请求状态码200位成功if (httpResp.getStatusLine().getStatusCode() != 200) {logger.error("【requestExecuteByte】请求失败 statusCode:{}", statusCode);return null;}if (httpResp.getEntity() == null) return null;ByteArrayOutputStream aos = new ByteArrayOutputStream();IOUtils.copy(httpResp.getEntity().getContent(), aos);return aos;} catch (Exception e) {logger.error("【httpClient】 requestExecuteByte Exception:{}", e.getMessage());return null;} finally {StreamClose.close(httpResp);request.releaseConnection();clientClose();}}/*** 设置请求头** @param httpReq 请求对象* @param headerMap 配置的请求头部*/private void setHeaders(HttpRequestBase httpReq, Map<String, String> headerMap) {httpReq.setConfig(reqConfig);if (headerMap == null) return;if (!headerMap.containsKey("Content-Type")) {httpReq.setHeader("Content-Type", "application/json;charset=UTF-8");}headerMap.forEach((k, v) -> {if (v == null || k == null) return;httpReq.setHeader(k, v);});}private void clientClose() {cm.closeExpiredConnections();// 关闭过期的链接cm.closeIdleConnections(30, TimeUnit.SECONDS); // 选择关闭 空闲30秒的链接semaphore.release();//释放令牌}/*** 获取响应的字符串** @param httpResp 请求响应的对象* @return 请求URL响应的字符内容*/private String getResponseStr(CloseableHttpResponse httpResp) {InputStream is = null;try {is = httpResp.getEntity().getContent();String charsetName = getCharsetName(httpResp);return IOUtils.toString(is, charsetName);} catch (IOException e) {logger.error("getResponseStr IOException:{}", e.getMessage());} finally {StreamClose.close(is);}return null;}/*** 获取响应中的字符格式** @param httpResp 请求响应的对象* @return 字符编码*/private String getCharsetName(CloseableHttpResponse httpResp) {String value = httpResp.getEntity().getContentType().getValue().trim();String[] contentTypes = value.split(";");String charsetName = StandardCharsets.UTF_8.displayName();//编码格式for (String type : contentTypes) {if (!type.trim().startsWith("charset")) continue;String[] split = type.split("=");return split[1];}return charsetName;}/*** 实例化方法*/public static HttpClientUtil getInstance() {if (httpClient != null) return httpClient;synchronized (HttpClientUtil.class) {if (httpClient != null) return httpClient;httpClient = new HttpClientUtil();}return httpClient;}private HttpClientUtil() {}
}
查看全文
99%的人还看了
相似问题
猜你感兴趣
版权申明
本文"基于httpclient依赖封装一个更适用自己业务场景的工具类":http://eshow365.cn/6-23898-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!