diff --git a/common/pom.xml b/common/pom.xml
index 83dbd819..7c4a7a13 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -87,13 +87,6 @@
${snakeyaml.version}
-
-
- org.apache.httpcomponents
- httpclient
- ${httpclient.version}
-
-
org.apache.commons
diff --git a/common/src/main/java/com/jeesite/common/web/http/HttpClientUtils.java b/common/src/main/java/com/jeesite/common/web/http/HttpClientUtils.java
index ac3aa296..4b7fe368 100644
--- a/common/src/main/java/com/jeesite/common/web/http/HttpClientUtils.java
+++ b/common/src/main/java/com/jeesite/common/web/http/HttpClientUtils.java
@@ -4,218 +4,225 @@
*/
package com.jeesite.common.web.http;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.security.GeneralSecurityException;
-import java.security.cert.CertificateException;
+import com.jeesite.common.codec.EncodeUtils;
+import com.jeesite.common.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509ExtendedTrustManager;
+import java.net.Socket;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.security.SecureRandom;
import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.List;
+import java.time.Duration;
import java.util.Map;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.NameValuePair;
-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.client.methods.HttpUriRequest;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.conn.ssl.TrustStrategy;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.message.BasicNameValuePair;
-import org.apache.http.ssl.SSLContextBuilder;
-import org.apache.http.util.EntityUtils;
-
-import com.jeesite.common.codec.EncodeUtils;
-
/**
- * HTTP客户端工具类(支持HTTPS)
+ * HTTP 客户端工具类(支持HTTPS)
* @author ThinkGem
- * @version 2017-3-27
+ * @version 2025-03-26
*/
public class HttpClientUtils {
-
+
+ private final static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
+ private static final HttpClient client = createHttpClient(60);
+
/**
- * http的get请求
- * @param url
+ * HTTP 的 GET 请求
*/
public static String get(String url) {
- return get(url, EncodeUtils.UTF_8);
- }
-
- /**
- * http的get请求
- * @param url
- */
- public static String get(String url, String charset) {
- HttpGet httpGet = new HttpGet(url);
- return executeRequest(httpGet, charset);
- }
-
- /**
- * http的get请求,增加异步请求头参数
- * @param url
- */
- public static String ajaxGet(String url) {
- return ajaxGet(url, EncodeUtils.UTF_8);
- }
-
- /**
- * http的get请求,增加异步请求头参数
- * @param url
- */
- public static String ajaxGet(String url, String charset) {
- HttpGet httpGet = new HttpGet(url);
- httpGet.setHeader("X-Requested-With", "XMLHttpRequest");
- return executeRequest(httpGet, charset);
+ return get(url, null, null);
}
/**
- * http的post请求,传递map格式参数
+ * HTTP 的 GET 请求,传递 Map 格式参数
+ */
+ public static String get(String url, Map dataMap) {
+ return get(url, dataMap, EncodeUtils.UTF_8);
+ }
+
+ /**
+ * HTTP 的 GET 请求,传递 Map 格式参数,支持指定编码
+ */
+ public static String get(String url, Map dataMap, String charset) {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(buildUrl(url, dataMap, charset)))
+ .GET()
+ .build();
+ return executeRequest(request);
+ }
+
+ /**
+ * HTTP 的 GET 请求,增加 ajax 请求头
+ */
+ public static String ajaxGet(String url) {
+ return ajaxGet(url, null, null);
+ }
+
+ /**
+ * HTTP 的 GET 请求,增加 ajax 请求头,传递 Map 格式参数
+ */
+ public static String ajaxGet(String url, Map dataMap) {
+ return ajaxGet(url, dataMap, EncodeUtils.UTF_8);
+ }
+
+ /**
+ * HTTP 的 GET 请求,增加 ajax 请求头,传递 Map 格式参数,支持指定编码
+ */
+ public static String ajaxGet(String url, Map dataMap, String charset) {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(buildUrl(url, dataMap, charset)))
+ .header("X-Requested-With", "XMLHttpRequest")
+ .GET()
+ .build();
+ return executeRequest(request);
+ }
+
+ /**
+ * 构建表单数据,Map 转换 params,支持指定编码
+ */
+ private static String buildUrl(String url, Map dataMap, String charset) {
+ if (dataMap == null) {
+ return url;
+ }
+ StringBuilder sb = new StringBuilder(url);
+ if (!url.contains("?")) {
+ sb.append("?");
+ } else if (!url.endsWith("&")) {
+ sb.append("&");
+ }
+ return sb + buildFormData(dataMap, charset);
+ }
+
+ /**
+ * HTTP 的 POST 请求,传递 Map 格式参数
*/
public static String post(String url, Map dataMap) {
return post(url, dataMap, EncodeUtils.UTF_8);
}
/**
- * http的post请求,传递map格式参数
+ * HTTP 的 POST 请求,传递 Map 格式参数,支持指定编码
*/
public static String post(String url, Map dataMap, String charset) {
- HttpPost httpPost = new HttpPost(url);
- try {
- if (dataMap != null){
- List nvps = new ArrayList();
- for (Map.Entry entry : dataMap.entrySet()) {
- nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
- }
- UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, charset);
- formEntity.setContentEncoding(charset);
- httpPost.setEntity(formEntity);
- }
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return executeRequest(httpPost, charset);
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .header("Content-Type", "application/x-www-form-urlencoded")
+ .POST(HttpRequest.BodyPublishers.ofString(buildFormData(dataMap, charset)))
+ .build();
+ return executeRequest(request);
}
/**
- * http的post请求,增加异步请求头参数,传递map格式参数
+ * HTTP 的 POST 请求,增加 ajax 请求头,传递 Map 格式参数
*/
public static String ajaxPost(String url, Map dataMap) {
return ajaxPost(url, dataMap, EncodeUtils.UTF_8);
}
/**
- * http的post请求,增加异步请求头参数,传递map格式参数
+ * HTTP 的 POST 请求,增加 ajax 请求头,传递 Map 格式参数,支持指定编码
*/
public static String ajaxPost(String url, Map dataMap, String charset) {
- HttpPost httpPost = new HttpPost(url);
- httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
- try {
- if (dataMap != null){
- List nvps = new ArrayList();
- for (Map.Entry entry : dataMap.entrySet()) {
- nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
- }
- UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, charset);
- formEntity.setContentEncoding(charset);
- httpPost.setEntity(formEntity);
- }
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return executeRequest(httpPost, charset);
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .header("X-Requested-With", "XMLHttpRequest")
+ .header("Content-Type", "application/x-www-form-urlencoded")
+ .POST(HttpRequest.BodyPublishers.ofString(buildFormData(dataMap, charset)))
+ .build();
+ return executeRequest(request);
}
/**
- * http的post请求,增加异步请求头参数,传递json格式参数
+ * 构建表单数据,Map 转换 params,支持指定编码
+ */
+ private static String buildFormData(Map dataMap, String charset) {
+ return dataMap.entrySet().stream()
+ .map(entry -> entry.getKey() + "="
+ + EncodeUtils.encodeUrl(entry.getValue(), charset))
+ .reduce((a, b) -> a + "&" + b)
+ .orElse(StringUtils.EMPTY);
+ }
+
+ /**
+ * HTTP 的 POST 请求,使用 json 请求头,传递 json 格式参数
*/
public static String ajaxPostJson(String url, String jsonString) {
return ajaxPostJson(url, jsonString, EncodeUtils.UTF_8);
}
/**
- * http的post请求,增加异步请求头参数,传递json格式参数
+ * HTTP 的 POST 请求,使用 json 请求头,传递 json 格式参数,支持指定编码
*/
public static String ajaxPostJson(String url, String jsonString, String charset) {
- HttpPost httpPost = new HttpPost(url);
- httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
-// try {
- StringEntity stringEntity = new StringEntity(jsonString, charset);// 解决中文乱码问题
- stringEntity.setContentEncoding(charset);
- stringEntity.setContentType("application/json");
- httpPost.setEntity(stringEntity);
-// } catch (UnsupportedEncodingException e) {
-// e.printStackTrace();
-// }
- return executeRequest(httpPost, charset);
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .header("X-Requested-With", "XMLHttpRequest")
+ .header("Content-Type", "application/json; charset="
+ + (StringUtils.isNotBlank(charset) ? charset : EncodeUtils.UTF_8))
+ .POST(HttpRequest.BodyPublishers.ofString(jsonString))
+ .build();
+ return executeRequest(request);
}
/**
- * 执行一个http请求,传递HttpGet或HttpPost参数
+ * 执行一个 http 请求,传递 HttpRequest 参数
*/
- public static String executeRequest(HttpUriRequest httpRequest) {
- return executeRequest(httpRequest, EncodeUtils.UTF_8);
+ public static String executeRequest(HttpRequest request) {
+ try {
+ return client.send(request, HttpResponse.BodyHandlers.ofString()).body();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
- /**
- * 执行一个http请求,传递HttpGet或HttpPost参数
- */
- public static String executeRequest(HttpUriRequest httpRequest, String charset) {
- CloseableHttpClient httpclient;
- if ("https".equals(httpRequest.getURI().getScheme())){
- httpclient = createSSLInsecureClient();
- }else{
- httpclient = HttpClients.createDefault();
- }
- String result = "";
+ public static HttpClient createHttpClient(long seconds) {
+ HttpClient client;
try {
- try {
- CloseableHttpResponse response = httpclient.execute(httpRequest);
- HttpEntity entity = null;
- try {
- entity = response.getEntity();
- result = EntityUtils.toString(entity, charset);
- } finally {
- EntityUtils.consume(entity);
- response.close();
- }
- } finally {
- httpclient.close();
- }
- }catch(IOException ex){
- ex.printStackTrace();
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, new TrustManager[]{new UnsafeX509ExtendedTrustManager()}, new SecureRandom());
+ client = HttpClient.newBuilder()
+ .sslContext(sslContext)
+ .connectTimeout(Duration.ofSeconds(seconds))
+ .build();
+ } catch (Exception e) {
+ logger.info(e.getMessage(), e);
+ client = HttpClient.newHttpClient();
}
- return result;
+ return client;
}
-
- /**
- * 创建 SSL连接
- */
- public static CloseableHttpClient createSSLInsecureClient() {
- try {
- SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(new TrustStrategy() {
- @Override
- public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- return true;
- }
- }).build();
- SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new HostnameVerifier() {
- @Override
- public boolean verify(String hostname, SSLSession session) {
- return true;
- }
- });
- return HttpClients.custom().setSSLSocketFactory(sslsf).build();
- } catch (GeneralSecurityException ex) {
- throw new RuntimeException(ex);
+
+ private static final class UnsafeX509ExtendedTrustManager extends X509ExtendedTrustManager {
+
+ private static final X509Certificate[] EMPTY_CERTIFICATES = new X509Certificate[0];
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] certificates, String authType) {
+ }
+ @Override
+ public void checkClientTrusted(X509Certificate[] certificates, String authType, Socket socket) {
+ }
+ @Override
+ public void checkClientTrusted(X509Certificate[] certificates, String authType, SSLEngine sslEngine) {
+ }
+ @Override
+ public void checkServerTrusted(X509Certificate[] certificates, String authType) {
+ }
+ @Override
+ public void checkServerTrusted(X509Certificate[] certificates, String authType, Socket socket) {
+ }
+ @Override
+ public void checkServerTrusted(X509Certificate[] certificates, String authType, SSLEngine sslEngine) {
+ }
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return EMPTY_CERTIFICATES;
}
}
diff --git a/common/src/test/java/com/jeesite/test/web/http/HttpClientUtilsTest.java b/common/src/test/java/com/jeesite/test/web/http/HttpClientUtilsTest.java
index ae9de7dc..8163dce8 100644
--- a/common/src/test/java/com/jeesite/test/web/http/HttpClientUtilsTest.java
+++ b/common/src/test/java/com/jeesite/test/web/http/HttpClientUtilsTest.java
@@ -4,8 +4,12 @@
*/
package com.jeesite.test.web.http;
+import com.jeesite.common.mapper.JsonMapper;
import com.jeesite.common.web.http.HttpClientUtils;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* HTTP客户端测试工具类(支持HTTPS)
* @author ThinkGem
@@ -14,8 +18,15 @@ import com.jeesite.common.web.http.HttpClientUtils;
public class HttpClientUtilsTest {
public static void main(String[] args) {
- String content = HttpClientUtils.get("https://jeesite.com");
- System.out.println(content);
+ String url = "https://vue.jeesite.com/js/a/sys/corpAdmin/treeData";
+ Map dataMap = new HashMap<>();
+ dataMap.put("isShowCode", "true");
+ dataMap.put("param1", "你好");
+ System.out.println(HttpClientUtils.get(url, dataMap));
+ System.out.println(HttpClientUtils.ajaxGet(url, dataMap));
+ System.out.println(HttpClientUtils.post(url, dataMap));
+ System.out.println(HttpClientUtils.ajaxPost(url, dataMap));
+ System.out.println(HttpClientUtils.ajaxPostJson(url, JsonMapper.toJson(dataMap)));
}
}
diff --git a/parent/pom.xml b/parent/pom.xml
index ac9ec344..89fc7131 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -31,7 +31,6 @@
2.0.51
2.2
2.3.9
- 4.5.14
1.21
2.19.0