|
@@ -0,0 +1,187 @@
|
|
|
+package com.caimei365.commodity.utils;
|
|
|
+
|
|
|
+import io.netty.handler.ssl.SslContextBuilder;
|
|
|
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
|
|
+import org.springframework.http.ResponseCookie;
|
|
|
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
|
|
+import org.springframework.util.LinkedMultiValueMap;
|
|
|
+import org.springframework.util.MultiValueMap;
|
|
|
+import org.springframework.web.reactive.function.client.WebClient;
|
|
|
+import reactor.netty.http.client.HttpClient;
|
|
|
+
|
|
|
+import java.time.Duration;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Description
|
|
|
+ *
|
|
|
+ * @author : Charles
|
|
|
+ * @date : 2021/2/23
|
|
|
+ */
|
|
|
+public class WebClientUtils {
|
|
|
+ /**
|
|
|
+ * 默认3分钟超时时间
|
|
|
+ */
|
|
|
+ private final static Duration DEFAULT_REQUEST_TIMEOUT = Duration.ofMinutes(3L);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 默认代理超时时间
|
|
|
+ */
|
|
|
+ private final static Long DEFAULT_PROXY_TIMEOUT_MILLIS = DEFAULT_REQUEST_TIMEOUT.toMillis();
|
|
|
+
|
|
|
+ //region 生成WebClient.Builder的方法
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 给了一个默认的WebClient,这个Client里面配置了默认请求超时时间
|
|
|
+ *
|
|
|
+ * @return 返回一个带超时时间的{@link WebClient.Builder}
|
|
|
+ */
|
|
|
+ public static WebClient.Builder getDefaultWebClientBuilder() {
|
|
|
+ return getWebClientBuilder(DEFAULT_REQUEST_TIMEOUT);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * [基础创建方法]
|
|
|
+ * 给了一个默认的WebClient,这个Client里面配置了指定了请求超时时间
|
|
|
+ *
|
|
|
+ * @param requestTimeOut 请求超时时间
|
|
|
+ * @return 返回一个带超时时间的{@link WebClient.Builder}
|
|
|
+ */
|
|
|
+ public static WebClient.Builder getWebClientBuilder(Duration requestTimeOut) {
|
|
|
+ if (requestTimeOut == null) {
|
|
|
+ requestTimeOut = DEFAULT_REQUEST_TIMEOUT;
|
|
|
+ }
|
|
|
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient
|
|
|
+ .create()
|
|
|
+ //重新定向开启
|
|
|
+ .followRedirect(true)
|
|
|
+ .responseTimeout(requestTimeOut)));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 给到一个带默认超时时间,并带有不校验任何SSL整数的WebClient
|
|
|
+ *
|
|
|
+ * @return 返回一个带默认超时时间和默认全局信任的SSL请求校验器{@link WebClient.Builder}
|
|
|
+ */
|
|
|
+ public static WebClient.Builder getWebClientBuilderWithSslTrust() {
|
|
|
+ return getWebClientBuilderWithSslTrust(DEFAULT_REQUEST_TIMEOUT);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 给到一个带超时时间,并带有不校验任何SSL整数的WebClient
|
|
|
+ *
|
|
|
+ * @param requestTimeOut 超时时间
|
|
|
+ * @return 返回一个带超时时间和默认全局信任的SSL请求校验器{@link WebClient.Builder}
|
|
|
+ */
|
|
|
+ public static WebClient.Builder getWebClientBuilderWithSslTrust(Duration requestTimeOut) {
|
|
|
+ return getWebClientBuilderWithSslTrust(requestTimeOut, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * [基础创建方法]
|
|
|
+ * 给到一个带超时时间,并带有不校验任何SSL整数的WebClient
|
|
|
+ *
|
|
|
+ * @param requestTimeOut 超时时间
|
|
|
+ * @param compressionEnabled 开启压缩?默认关闭
|
|
|
+ * @return 返回一个带超时时间和默认全局信任的SSL请求校验器{@link WebClient.Builder}
|
|
|
+ */
|
|
|
+ public static WebClient.Builder getWebClientBuilderWithSslTrust(Duration requestTimeOut, boolean compressionEnabled) {
|
|
|
+ if (requestTimeOut == null) {
|
|
|
+ requestTimeOut = DEFAULT_REQUEST_TIMEOUT;
|
|
|
+ }
|
|
|
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient
|
|
|
+ .create()
|
|
|
+ //重新定向开启
|
|
|
+ .followRedirect(true)
|
|
|
+ //这里注入了一个抛弃一切SSL认证的sslContext
|
|
|
+ .secure(sslContextSpec -> sslContextSpec.sslContext(SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)))
|
|
|
+ .responseTimeout(requestTimeOut)
|
|
|
+ .compress(compressionEnabled)
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 给到一个带超时时间,带代理,并带有不校验任何SSL整数的WebClient
|
|
|
+ *
|
|
|
+ * @param requestTimeOut 超时时间
|
|
|
+ * @param proxyDO 代理实体
|
|
|
+ * @return 返回一个带超时时间和默认全局信任的SSL请求校验器{@link WebClient.Builder}
|
|
|
+ */
|
|
|
+ /*public static WebClient.Builder getWebClientBuilderWithSslTrustAndPolicy(Duration requestTimeOut, ProxyDO proxyDO) {
|
|
|
+ return getWebClientBuilderWithSslTrustAndPolicy(requestTimeOut, proxyDO, false);
|
|
|
+ }*/
|
|
|
+
|
|
|
+ /**
|
|
|
+ * [基础创建方法]
|
|
|
+ * 给到一个带超时时间,带代理,并带有不校验任何SSL整数的WebClient
|
|
|
+ *
|
|
|
+ * @param requestTimeOut 超时时间
|
|
|
+ * @param proxyDO 代理实体
|
|
|
+ * @param compressionEnabled 开启压缩?默认关闭
|
|
|
+ * @return 返回一个带超时时间和默认全局信任的SSL请求校验器{@link WebClient.Builder}
|
|
|
+ */
|
|
|
+ /*public static WebClient.Builder getWebClientBuilderWithSslTrustAndPolicy(Duration requestTimeOut, ProxyDO proxyDO, boolean compressionEnabled) {
|
|
|
+ if (requestTimeOut == null) {
|
|
|
+ requestTimeOut = DEFAULT_REQUEST_TIMEOUT;
|
|
|
+ }
|
|
|
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient
|
|
|
+ .create()
|
|
|
+ //这里注入了一个抛弃一切SSL认证的sslContext
|
|
|
+ .secure(sslContextSpec -> sslContextSpec.sslContext(SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)))
|
|
|
+ .responseTimeout(requestTimeOut)
|
|
|
+ .compress(compressionEnabled)
|
|
|
+ //重新定向开启
|
|
|
+ .followRedirect(true)
|
|
|
+ .tcpConfiguration(tcpClient -> tcpClient.proxy(
|
|
|
+ p -> {
|
|
|
+ ProxyProvider.Builder pb = p.type(ProxyProvider.Proxy.HTTP)
|
|
|
+ .address(InetSocketAddress.createUnresolved(proxyDO.getServiceAddress(), Integer.parseInt(proxyDO.getPort())));
|
|
|
+ if (StringUtils.isNotEmpty(proxyDO.getUserName())) {
|
|
|
+ pb.username(proxyDO.getUserName())
|
|
|
+ .password(v -> proxyDO.getPassword());
|
|
|
+ }
|
|
|
+ Long proxyTimeOutMillis = proxyDO.getProxyTimeOutMillis();
|
|
|
+ if (proxyTimeOutMillis != null && proxyTimeOutMillis > 0) {
|
|
|
+ pb.connectTimeoutMillis(proxyTimeOutMillis);
|
|
|
+ } else {
|
|
|
+ pb.connectTimeoutMillis(DEFAULT_PROXY_TIMEOUT_MILLIS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ))
|
|
|
+ ));
|
|
|
+ }*/
|
|
|
+
|
|
|
+ //endregion
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将http相应中的Cookie转换为用于http请求中的cookie
|
|
|
+ * 方法中仅进行简单转换,不会对Cookie有效期等进行判断
|
|
|
+ *
|
|
|
+ * @param responseCookie 需要被转换的cookie
|
|
|
+ * @return 返回可以用于请求的Cookies
|
|
|
+ */
|
|
|
+ public static MultiValueMap<String, String> transformResponseCookiesToRequestCookies(MultiValueMap<String, ResponseCookie> responseCookie) {
|
|
|
+ MultiValueMap<String, String> ret = new LinkedMultiValueMap<>();
|
|
|
+ if (responseCookie == null || responseCookie.size() == 0) {
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ for (Map.Entry<String, List<ResponseCookie>> entity : responseCookie.entrySet()) {
|
|
|
+ String key = entity.getKey();
|
|
|
+ List<ResponseCookie> value = entity.getValue();
|
|
|
+ int size = value.size();
|
|
|
+ if (size == 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ List<String> cookies = new ArrayList<>(size);
|
|
|
+ for (ResponseCookie cookie : value) {
|
|
|
+ cookies.add(cookie.getValue());
|
|
|
+ }
|
|
|
+ ret.addAll(key, cookies);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+}
|