package com.ruoyi.common.utils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.github.pagehelper.util.StringUtil; import com.ruoyi.common.exception.HttpRequestException; import com.ruoyi.common.utils.http.HttpEntity; import com.ruoyi.common.utils.json.JsonRequestBody; import com.ruoyi.common.utils.json.JsonResponseBody; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.Charsets; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.EntityEnclosingMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.httpclient.params.HttpClientParams; import org.springframework.util.Assert; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.Locale; import java.util.Map; @Slf4j public class HttpUtil { protected static final int DEFAULT_STATUS_ERROR_CODE = 100001;//默认http异常状态码 protected static final String CONTENT_TYPE = "Content-Type"; protected static final String APPLICATION_JSON = "application/json"; protected static final String APPLICATION_JSON_UTF8 = "application/json; charset=utf-8"; protected static final String TEXT_XML = "text/xml"; protected static final String TEXT_XML_UTF8 = "text/xml; charset=utf-8"; protected static final int OK = 200; /** * 空的报文头 */ protected static final Map EMPTY_HEADERS = new HashMap(0); /** * 编码错误 */ protected static final int ENCODING_ERROR_CODE = 999997; /** * HTTP 错误: 死锁、文件过大等文件 */ protected static final int HTTP_ERROR_CODE = 999996; /** * IO 错误 */ protected static final int IO_ERROR_CODE = 999995; /** * 响应为null */ protected static final int RESPONSE_NULL_ERROR_CODE = 999994; protected static final String USER_IP_KEY = "x-remoteip"; protected static final String TEXT_NORMAL = "application/x-www-form-urlencoded; charset=utf-8"; protected static final HttpClient httpClient = getHttpClient(); private static final SimpleDateFormat formatHttpData = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); private static HttpClient getHttpClient() { // 此处运用连接池技术。 MultiThreadedHttpConnectionManager manager = new MultiThreadedHttpConnectionManager(); // 设定参数:与每个主机的最大连接数 manager.getParams().setDefaultMaxConnectionsPerHost(100); // 设定参数:客户端的总连接数 manager.getParams().setMaxTotalConnections(400); // 设置连接超时时间,单位:毫秒 manager.getParams().setConnectionTimeout(30000); // 设置请求读取超时时间,单位:毫秒 manager.getParams().setSoTimeout(30000); // 设置从连接池中获取链接时间, 单位:毫秒 manager.getParams().setParameter(HttpClientParams.CONNECTION_MANAGER_TIMEOUT, 8000); // 使用连接池技术创建HttpClient对象 HttpClient httpClient = new HttpClient(manager); return httpClient; } public static String postJsonRequest(String url, String request) throws HttpRequestException { Assert.hasLength(url, "请求url不能为空字符串。"); EntityEnclosingMethod httpMethod = new PostMethod(url); httpMethod.addRequestHeader("Content-Type", "application/json; charset=UTF-8"); setHeaderRequestId(httpMethod); try { RequestEntity entity = new StringRequestEntity(request, "application/json", "utf-8"); httpMethod.setRequestEntity(entity); int resultCode = httpClient.executeMethod(httpMethod); InputStream inputStream = httpMethod.getResponseBodyAsStream(); if (inputStream == null) { throw new HttpRequestException(RESPONSE_NULL_ERROR_CODE, "响应为null"); } BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuffer stringBuffer = new StringBuffer(); String str = ""; while ((str = reader.readLine()) != null) { stringBuffer.append(str); } reader.close(); String respJson = stringBuffer.toString(); // String respJson = httpMethod.getResponseBodyAsString(); if (resultCode == OK) { return respJson; } else { throw new HttpRequestException(resultCode, respJson); } } catch (UnsupportedEncodingException e) { throw new HttpRequestException(ENCODING_ERROR_CODE, e); } catch (HttpException e) { throw new HttpRequestException(HTTP_ERROR_CODE, e); } catch (IOException e) { throw new HttpRequestException(IO_ERROR_CODE, e); } finally { if (httpMethod != null) { httpMethod.releaseConnection(); } } } /** * json的post请求 * * @param url 请求url * @param reqEntity 请求头与请求体的封装 * @param respBodyClass 响应体类型 * @return 返回的响应结果 */ @SuppressWarnings("unchecked") public static HttpEntity postJsonRequestV2(String url, HttpEntity reqEntity, Class respBodyClass) { Assert.hasLength(url, "请求url不能为空字符串。"); Assert.notNull(reqEntity, "请求request不能为null。"); Assert.notNull(reqEntity.getBody(), "Post请求body不能为null。"); EntityEnclosingMethod httpMethod = new PostMethod(url); //设置header信息 Map headers = reqEntity.getHeaders(); //若传入报文头,则设置值 if (headers != HttpEntity.EMPTY_HEADERS) { setReqHeaders(headers, httpMethod); } //设置body信息 String reqJson = JSON.toJSONString(reqEntity.getBody()); String charset = com.google.common.base.Charsets.UTF_8.name(); // 发送含xml消息体的对象 try { RequestEntity entity = new StringRequestEntity(reqJson, APPLICATION_JSON, charset); httpMethod.setRequestEntity(entity); // 执行请求并接收响应码 int resultCode = httpClient.executeMethod(httpMethod); InputStream inputStream = httpMethod.getResponseBodyAsStream(); if (inputStream == null) { throw new HttpRequestException(RESPONSE_NULL_ERROR_CODE, "响应为null"); } BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("GB2312"))); StringBuffer stringBuffer = new StringBuffer(); String str = ""; while ((str = reader.readLine()) != null) { stringBuffer.append(str); } reader.close(); String respStr = stringBuffer.toString(); //String respStr = httpMethod.getResponseBodyAsString(); if (resultCode == OK) { //响应头 Map respHeaders = getRespHeaders(httpMethod); //响应体 HttpEntity rep = null; if (isNullOrEmpty(respStr) || null == respBodyClass) { rep = new HttpEntity(respHeaders, null); // 无响应 } else { if (respBodyClass != String.class) { RESPBODY respBody = JSON.parseObject(respStr, respBodyClass); rep = new HttpEntity(respHeaders, respBody); } else { rep = new HttpEntity(respHeaders, (RESPBODY) new String(respStr.getBytes("ISO8859-1"), StandardCharsets.UTF_8)); } } return rep; } else if (resultCode == DEFAULT_STATUS_ERROR_CODE) { JSONObject model = JSON.parseObject(respStr); throw new HttpRequestException(model.getIntValue("code"), model.getString("msg")); } else { throw new HttpRequestException(resultCode, respStr); } } catch (UnsupportedEncodingException e) { throw new HttpRequestException(ENCODING_ERROR_CODE, e); } catch (HttpException e) { throw new HttpRequestException(HTTP_ERROR_CODE, e); } catch (IOException e) { throw new HttpRequestException(IO_ERROR_CODE, e); } finally { if (httpMethod != null) { httpMethod.releaseConnection(); } } } public static HttpEntity postJsonRequest(String url, HttpEntity reqEntity, Class respBodyClass) { Assert.hasLength(url, "请求url不能为空字符串。"); Assert.notNull(reqEntity, "请求request不能为null。"); Assert.notNull(reqEntity.getBody(), "Post请求body不能为null。"); EntityEnclosingMethod httpMethod = new PostMethod(url); //设置header信息 Map headers = reqEntity.getHeaders(); //若传入报文头,则设置值 if (headers != HttpEntity.EMPTY_HEADERS) { setReqHeaders(headers, httpMethod); } //设置body信息 String reqJson = JSON.toJSONString(reqEntity.getBody()); String charset = Charsets.UTF_8.name(); // 发送含xml消息体的对象 try { RequestEntity entity = new StringRequestEntity(reqJson, APPLICATION_JSON, charset); httpMethod.setRequestEntity(entity); // 执行请求并接收响应码 int resultCode = httpClient.executeMethod(httpMethod); InputStream inputStream = httpMethod.getResponseBodyAsStream(); if (inputStream == null) { throw new HttpRequestException(RESPONSE_NULL_ERROR_CODE, "响应为null"); } BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuffer stringBuffer = new StringBuffer(); String str = ""; while ((str = reader.readLine()) != null) { stringBuffer.append(str); } reader.close(); String respStr = stringBuffer.toString(); if (resultCode == OK) { //响应头 Map respHeaders = getRespHeaders(httpMethod); //响应体 HttpEntity rep = null; if (isNullOrEmpty(respStr) || null == respBodyClass) { rep = new HttpEntity(respHeaders, null); ;// 无响应 } else { RESPBODY respBody = JSON.parseObject(respStr, respBodyClass); rep = new HttpEntity(respHeaders, respBody); } return rep; } else if (resultCode == DEFAULT_STATUS_ERROR_CODE) { JSONObject model = JSON.parseObject(respStr); throw new HttpRequestException(model.getIntValue("code"), model.getString("msg")); } else { throw new HttpRequestException(resultCode, respStr); } } catch (UnsupportedEncodingException e) { throw new HttpRequestException(ENCODING_ERROR_CODE, e); } catch (HttpException e) { throw new HttpRequestException(HTTP_ERROR_CODE, e); } catch (IOException e) { throw new HttpRequestException(IO_ERROR_CODE, e); } finally { if (httpMethod != null) { httpMethod.releaseConnection(); } } } public static String postFormRequest(String baseUrl, Map params, Map headers, String body) { HttpURLConnection connection = null; BufferedReader reader = null; try { // 构建完整的URL(包含查询参数) String fullUrl = buildUrlWithParams(baseUrl, params); URL requestUrl = new URL(fullUrl); connection = (HttpURLConnection) requestUrl.openConnection(); // 设置请求方法 connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setDoInput(true); connection.setUseCaches(false); // 设置请求头 if (headers != null) { for (Map.Entry entry : headers.entrySet()) { connection.setRequestProperty(entry.getKey(), entry.getValue()); } } // 设置默认的Content-Type if (!connection.getRequestProperties().containsKey("Content-Type")) { connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); } // 如果有请求体,写入数据 if (body != null && !body.isEmpty()) { try (OutputStream os = connection.getOutputStream()) { byte[] input = body.getBytes(StandardCharsets.UTF_8); os.write(input, 0, input.length); } } // 获取响应码 int responseCode = connection.getResponseCode(); // 读取响应 StringBuilder response = new StringBuilder(); if (responseCode == HttpURLConnection.HTTP_OK) { reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); } else { reader = new BufferedReader(new InputStreamReader(connection.getErrorStream())); } String line; while ((line = reader.readLine()) != null) { response.append(line); } return response.toString(); } catch (Exception e) { throw new RuntimeException("POST请求失败: " + e.getMessage(), e); } finally { // 关闭连接 if (reader != null) { try { reader.close(); } catch (Exception e) { /* ignore */ } } if (connection != null) { connection.disconnect(); } } } private static String buildUrlWithParams(String baseUrl, Map params) { if (params == null || params.isEmpty()) { return baseUrl; } StringBuilder urlBuilder = new StringBuilder(baseUrl); boolean firstParam = true; for (Map.Entry entry : params.entrySet()) { if (firstParam) { urlBuilder.append("?"); firstParam = false; } else { urlBuilder.append("&"); } try { urlBuilder.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.toString())).append("=").append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.toString())); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } return urlBuilder.toString(); } // public static String postFormRequest(String url, Map params,Map headers) throws HttpRequestException { // Assert.hasLength(url, "请求url不能为空字符串。"); // Assert.notNull(params, "请求params不能为空。"); // // PostMethod httpMethod = new PostMethod(url); // // httpMethod.addRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); // // if(!ObjectUtils.isEmpty(headers)) { // httpMethod.addRequestHeader(headers.get(), "application/json"); // } // // try { // // 发送请求参数 // StringBuilder param = new StringBuilder(); // for (Map.Entry entry : params.entrySet()) { // if (param.length() > 0) { // param.append("&"); // } // param.append(entry.getKey()); // param.append("="); // param.append(entry.getValue()); // } // // RequestEntity entity = new StringRequestEntity(param.toString(), "application/json", "utf-8"); // httpMethod.setRequestEntity(entity); // // 执行请求并接收响应码 // int resultCode = httpClient.executeMethod(httpMethod); // // String respJson = httpMethod.getResponseBodyAsString(); // if (resultCode == OK) { // return respJson; // } else { // throw new HttpRequestException(resultCode, respJson); // } // } catch (UnsupportedEncodingException e) { // throw new HttpRequestException(ENCODING_ERROR_CODE, e); // } catch (HttpException e) { // throw new HttpRequestException(HTTP_ERROR_CODE, e); // } catch (IOException e) { // throw new HttpRequestException(IO_ERROR_CODE, e); // } finally { // if (httpMethod != null) { // httpMethod.releaseConnection(); // } // } // } private static Map getRespHeaders(HttpMethodBase httpMethod) { //得到响应头 Header[] respHeaders = httpMethod.getResponseHeaders(); Map headers = new HashMap(respHeaders.length); for (Header header : respHeaders) headers.put(header.getName(), header.getValue()); return headers; } protected static void setReqHeaders(Map headers, HttpMethodBase httpMethod) { //设置请求头 for (Map.Entry header : headers.entrySet()) { httpMethod.addRequestHeader(header.getKey(), header.getValue()); } } protected static void setHeaderRequestId(HttpMethodBase httpMethod) { //设置请求头 ServletRequestAttributes req = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (null != req) { String requestId = req.getRequest().getHeader("x-request-id"); if (StringUtil.isNotEmpty(requestId)) { httpMethod.addRequestHeader("x-request-id", requestId); log.info("header中x-request-id值为:{}", requestId); } } } private static boolean isNullOrEmpty(String obj) { if (obj == null || obj.isEmpty()) { return true; } return false; } }