first commit
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
package com.mgm.mcrm.common.services;
|
||||
|
||||
import com.mgm.mcrm.common.httpclient.HttpSslSupport;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
||||
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
|
||||
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.hc.core5.http.config.Registry;
|
||||
import org.apache.hc.core5.http.config.RegistryBuilder;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.PreDestroy;
|
||||
|
||||
/**
|
||||
* HttpClient 配置服务
|
||||
*
|
||||
* 提供统一的 HttpClient 配置管理,包括:
|
||||
* - SSL 配置
|
||||
* - 连接池配置
|
||||
* - 请求超时配置
|
||||
* - HttpClient 实例创建
|
||||
*
|
||||
* @author Aaka
|
||||
*/
|
||||
@Service
|
||||
public class HttpClientService {
|
||||
|
||||
private CloseableHttpClient httpClient;
|
||||
private PoolingHttpClientConnectionManager connectionManager;
|
||||
|
||||
/**
|
||||
* 创建带 SSL 配置的 HttpClient(使用连接池)
|
||||
*
|
||||
* @param maxTotal 连接池最大连接数,默认 100
|
||||
* @param maxPerRoute 每个路由最大连接数,默认 10
|
||||
* @param connectionRequestTimeout 连接请求超时时间(秒),默认 5
|
||||
* @param responseTimeout 响应超时时间(秒),默认 10
|
||||
* @param redirectsEnabled 是否启用重定向,默认 false
|
||||
* @return 配置好的 CloseableHttpClient 实例
|
||||
*/
|
||||
public CloseableHttpClient createHttpClientWithSSL(
|
||||
Integer maxTotal,
|
||||
Integer maxPerRoute,
|
||||
Integer connectionRequestTimeout,
|
||||
Integer responseTimeout,
|
||||
Boolean redirectsEnabled) {
|
||||
|
||||
// 使用 SSLs 配置 SSL
|
||||
HttpSslSupport ssls = HttpSslSupport.getInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
SSLConnectionSocketFactory sslConnFactory = ssls.getSSLCONNSF(HttpSslSupport.SSLProtocolVersion.TLSv1_2);
|
||||
|
||||
// 注意:ConnectionSocketFactory 和 SSLConnectionSocketFactory 在 HttpClient 5 中被标记为 deprecated,
|
||||
// 但这是目前唯一可用的方式,新的 API 尚未稳定
|
||||
@SuppressWarnings("deprecation")
|
||||
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
|
||||
.register("https", sslConnFactory)
|
||||
.build();
|
||||
|
||||
// 注意:PoolingHttpClientConnectionManager 构造函数在 HttpClient 5 中被标记为 deprecated,
|
||||
// 但这是目前唯一可用的方式
|
||||
@SuppressWarnings("deprecation")
|
||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
|
||||
connManager.setMaxTotal(maxTotal != null ? maxTotal : 100);
|
||||
connManager.setDefaultMaxPerRoute(maxPerRoute != null ? maxPerRoute : 10);
|
||||
|
||||
this.connectionManager = connManager;
|
||||
|
||||
// 配置请求参数(超时、编码等)
|
||||
RequestConfig requestConfig = createRequestConfig(
|
||||
connectionRequestTimeout,
|
||||
responseTimeout,
|
||||
redirectsEnabled);
|
||||
|
||||
CloseableHttpClient client = HttpClients.custom()
|
||||
.setConnectionManager(connManager)
|
||||
.setDefaultRequestConfig(requestConfig)
|
||||
.setConnectionManagerShared(false)
|
||||
.build();
|
||||
|
||||
this.httpClient = client;
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建带 SSL 配置的 HttpClient(使用默认配置)
|
||||
*
|
||||
* @return 配置好的 CloseableHttpClient 实例
|
||||
*/
|
||||
public CloseableHttpClient createHttpClientWithSSL() {
|
||||
return createHttpClientWithSSL(null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 RequestConfig 配置
|
||||
*
|
||||
* @param connectionRequestTimeout 连接请求超时时间(秒),默认 5
|
||||
* @param responseTimeout 响应超时时间(秒),默认 10
|
||||
* @param redirectsEnabled 是否启用重定向,默认 false
|
||||
* @return 配置好的 RequestConfig 实例
|
||||
*/
|
||||
public RequestConfig createRequestConfig(
|
||||
Integer connectionRequestTimeout,
|
||||
Integer responseTimeout,
|
||||
Boolean redirectsEnabled) {
|
||||
|
||||
RequestConfig.Builder builder = RequestConfig.custom();
|
||||
|
||||
if (connectionRequestTimeout != null) {
|
||||
builder.setConnectionRequestTimeout(Timeout.ofSeconds(connectionRequestTimeout));
|
||||
} else {
|
||||
builder.setConnectionRequestTimeout(Timeout.ofSeconds(5));
|
||||
}
|
||||
|
||||
if (responseTimeout != null) {
|
||||
builder.setResponseTimeout(Timeout.ofSeconds(responseTimeout));
|
||||
} else {
|
||||
builder.setResponseTimeout(Timeout.ofSeconds(10));
|
||||
}
|
||||
|
||||
if (redirectsEnabled != null) {
|
||||
builder.setRedirectsEnabled(redirectsEnabled);
|
||||
} else {
|
||||
builder.setRedirectsEnabled(false);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建默认的 RequestConfig 配置
|
||||
*
|
||||
* @return 配置好的 RequestConfig 实例
|
||||
*/
|
||||
public RequestConfig createDefaultRequestConfig() {
|
||||
return createRequestConfig(null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前管理的 HttpClient 实例
|
||||
*
|
||||
* @return CloseableHttpClient 实例,如果未创建则返回 null
|
||||
*/
|
||||
public CloseableHttpClient getHttpClient() {
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭 HttpClient 和连接管理器
|
||||
* 在 Spring Bean 销毁时自动调用
|
||||
*/
|
||||
@PreDestroy
|
||||
public void close() {
|
||||
if (httpClient != null) {
|
||||
try {
|
||||
httpClient.close();
|
||||
} catch (Exception e) {
|
||||
// 忽略关闭异常
|
||||
}
|
||||
}
|
||||
if (connectionManager != null) {
|
||||
connectionManager.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
package com.mgm.mcrm.common.services;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.mgm.mcrm.common.dtos.HttpResult;
|
||||
import com.mgm.mcrm.common.enums.HttpMethods;
|
||||
import com.mgm.mcrm.common.httpclient.HttpClientExecutor;
|
||||
import com.mgm.mcrm.common.httpclient.HttpRequestOptions;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 請求服務
|
||||
* @author Aaka
|
||||
*/
|
||||
@Service
|
||||
public class HttpService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(HttpService.class);
|
||||
|
||||
|
||||
@Resource
|
||||
@Qualifier("httpClientWithSSL")
|
||||
private CloseableHttpClient httpClient;
|
||||
|
||||
@Resource
|
||||
@Qualifier("httpRequestConfig")
|
||||
private RequestConfig requestConfig;
|
||||
|
||||
@Value("${daylight.url}")
|
||||
private String daylightUrl;
|
||||
|
||||
public String sslGet(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||
|
||||
// todo 在這裏需要把請求頭的信息插入到數據庫裏
|
||||
log.info("======sslGet======url:{}===========headers:{} =============== map:{}", daylightUrl + url,JSON.toJSONString(headers),JSON.toJSONString(map));
|
||||
// 使用 HttpRequestOptions 配置 GET 请求(带参数)
|
||||
HttpRequestOptions options = HttpRequestOptions.create()
|
||||
.url(daylightUrl + url)
|
||||
.timeout(requestConfig)
|
||||
.map(map)
|
||||
.encoding("utf-8")
|
||||
.client(httpClient);
|
||||
|
||||
String result = HttpClientExecutor.get(options, headers);
|
||||
log.info("====== GET request result:{}", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 HttpConfig 配置 POST 请求(form-urlencoded 格式)
|
||||
* @param url 請求路徑
|
||||
* @param headers 請求頭
|
||||
* @param map 請求參數
|
||||
* @return 接口結果的json數據
|
||||
* @throws Exception 異常
|
||||
*/
|
||||
public String sslPostForm(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||
log.info("======sslPostForm======url:{}===========headers:{} =============== map:{}", daylightUrl + url,JSON.toJSONString(headers),JSON.toJSONString(map));
|
||||
// 使用 HttpRequestOptions 配置 POST 请求(form-urlencoded 格式)
|
||||
HttpRequestOptions options = HttpRequestOptions.create()
|
||||
.url(daylightUrl + url)
|
||||
.timeout(requestConfig)
|
||||
.method(HttpMethods.POST)
|
||||
.map(map) // 使用 map,会自动转换为 form-urlencoded
|
||||
.encoding("utf-8")
|
||||
.client(httpClient);
|
||||
|
||||
String result = HttpClientExecutor.post(options, headers);
|
||||
log.info("====== POST Form request result:{}", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 HttpConfig 配置 POST 请求(JSON 格式)
|
||||
* @param url 請求路徑
|
||||
* @param headers 請求頭
|
||||
* @param map 請求參數
|
||||
* @return 接口結果的json數據
|
||||
* @throws Exception 異常
|
||||
*/
|
||||
public String sslPostJson(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||
log.info("======sslPostJson======url:{}===========headers:{} =============== map:{}", daylightUrl + url,JSON.toJSONString(headers),JSON.toJSONString(map));
|
||||
// 使用 HttpRequestOptions 配置 POST 请求(JSON 格式)
|
||||
HttpRequestOptions options = HttpRequestOptions.create()
|
||||
.url(daylightUrl + url)
|
||||
.timeout(requestConfig)
|
||||
.method(HttpMethods.POST)
|
||||
.json(JSON.toJSONString(map)) // 使用 map,会自动转换为 json
|
||||
.encoding("utf-8")
|
||||
.client(httpClient);
|
||||
|
||||
String result = HttpClientExecutor.post(options, headers);
|
||||
log.info("====== POST Json request result:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String sslPostJsonContent(String url, Header[] headers, String jsonContent) throws Exception {
|
||||
// 使用 HttpRequestOptions 配置 POST 请求(JSON 格式)
|
||||
HttpRequestOptions options = HttpRequestOptions.create()
|
||||
.url(daylightUrl + url)
|
||||
.timeout(requestConfig)
|
||||
.method(HttpMethods.POST)
|
||||
.json(jsonContent)
|
||||
.encoding("utf-8")
|
||||
.client(httpClient);
|
||||
|
||||
return HttpClientExecutor.post(options, headers);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 使用 HttpConfig 配置 PUT 请求
|
||||
* @param url 請求路徑
|
||||
* @param headers 請求頭
|
||||
* @param map 請求參數
|
||||
* @return 接口結果的json數據
|
||||
* @throws Exception 異常
|
||||
*/
|
||||
public String sslPut(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||
log.info("======sslPut======url:{}===========headers:{} =============== map:{}", daylightUrl + url,JSON.toJSONString(headers),JSON.toJSONString(map));
|
||||
HttpRequestOptions options = HttpRequestOptions.create()
|
||||
.url(daylightUrl + url)
|
||||
.timeout(requestConfig)
|
||||
.method(HttpMethods.PUT)
|
||||
.json(JSON.toJSONString(map))
|
||||
.encoding("utf-8")
|
||||
.client(httpClient);
|
||||
String result = HttpClientExecutor.execute(options, headers);
|
||||
log.info("====== PUT request result:{}", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 HttpConfig 配置 Delete 请求
|
||||
* @param url 請求路徑
|
||||
* @param headers 請求頭
|
||||
* @param map 請求參數
|
||||
* @return 接口結果的json數據
|
||||
* @throws Exception 異常
|
||||
*/
|
||||
public String sslPutDelete(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||
log.info("======sslPutDelete======url:{}===========headers:{} =============== map:{}", daylightUrl + url,JSON.toJSONString(headers),JSON.toJSONString(map));
|
||||
HttpRequestOptions options = HttpRequestOptions.create()
|
||||
.url(daylightUrl + url)
|
||||
.timeout(requestConfig)
|
||||
.method(HttpMethods.DELETE)
|
||||
.client(httpClient);
|
||||
String result = HttpClientExecutor.execute(options, headers);
|
||||
System.out.println("DELETE 请求结果:\n" + result);
|
||||
log.info("====== DELETE request result:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 HttpConfig 配置 Delete 请求
|
||||
* @param url 請求路徑
|
||||
* @param headers 請求頭
|
||||
* @param map 要传的数据
|
||||
* @return 接口結果的json數據
|
||||
* @throws Exception 異常
|
||||
*/
|
||||
public HttpResult sslPostHttpResult(String url, Header[] headers, Map<String,Object> map) throws Exception {
|
||||
log.info("======sslPutDelete======url:{}===========headers:{}", daylightUrl + url,JSON.toJSONString(headers));
|
||||
HttpRequestOptions postConfig = HttpRequestOptions.create()
|
||||
.url(daylightUrl + url)
|
||||
.timeout(requestConfig)
|
||||
.json(JSON.toJSONString(map))
|
||||
.method(HttpMethods.POST)
|
||||
.client(httpClient);
|
||||
HttpResult result = HttpClientExecutor.sendAndPostResp(postConfig, headers);
|
||||
System.out.println("POST 请求结果:\n" + result);
|
||||
log.info("====== POST request result:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public HttpResult sslGetHttpResult(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||
|
||||
// todo 在這裏需要把請求頭的信息插入到數據庫裏
|
||||
log.info("======sslGet======url:{}===========headers:{} =============== map:{}", daylightUrl + url,JSON.toJSONString(headers),JSON.toJSONString(map));
|
||||
// 使用 HttpConfig 配置 GET 请求(带参数)
|
||||
HttpRequestOptions getConfig = HttpRequestOptions.create()
|
||||
.url(daylightUrl + url)
|
||||
.timeout(requestConfig)
|
||||
.map(map)
|
||||
.encoding("utf-8")
|
||||
.client(httpClient);
|
||||
|
||||
HttpResult result = HttpClientExecutor.sendAndGetResp(getConfig, headers);
|
||||
log.info("====== GET request result:{}", result.getResult());
|
||||
|
||||
Map<String, String> mapResult = JSON.parseObject(result.getResult(), Map.class);
|
||||
log.info("====== GET request result:{}", mapResult.get("results"));
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.mgm.mcrm.common.services;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.mgm.mcrm.basesetting.property.dtos.response.TokenResponse;
|
||||
import com.mgm.mcrm.common.httpclient.HttpHeaderBuilder;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class HttpTokenService {
|
||||
@Resource
|
||||
private HttpService httpService;
|
||||
|
||||
@Value("${token.url}")
|
||||
private String tokenUrl;
|
||||
|
||||
@Value("${token.username}")
|
||||
private String username;
|
||||
|
||||
@Value("${token.password}")
|
||||
private String password;
|
||||
|
||||
@Value("${token.grant-type}")
|
||||
private String grantType;
|
||||
|
||||
@Value("${token.client-id}")
|
||||
private String clientId;
|
||||
|
||||
@Value("${token.client-secret}")
|
||||
private String clientSecret;
|
||||
|
||||
public TokenResponse getToken() throws Exception {
|
||||
// 1. 先獲取 token url
|
||||
// --- headers ---
|
||||
Header[] headers = HttpHeaderBuilder.create()
|
||||
.contentType("application/x-www-form-urlencoded")
|
||||
.build();
|
||||
// --- 參數 --
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("username", username);
|
||||
map.put("password", password);
|
||||
map.put("grant_type", grantType);
|
||||
map.put("client_id", clientId);
|
||||
map.put("client_secret", clientSecret);
|
||||
|
||||
String re = httpService.sslPostForm("/connect/token", headers, map);
|
||||
|
||||
return JSON.parseObject(re, TokenResponse.class);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user