HttpClientUtils.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. package com.phm.manage.util;
  2. import java.time.Duration;
  3. import java.util.Map;
  4. import java.util.Objects;
  5. import java.util.concurrent.TimeUnit;
  6. import org.springframework.beans.factory.annotation.Value;
  7. import org.springframework.http.MediaType;
  8. import org.springframework.http.client.reactive.ClientHttpConnector;
  9. import org.springframework.http.client.reactive.ReactorClientHttpConnector;
  10. import org.springframework.util.LinkedMultiValueMap;
  11. import org.springframework.util.MultiValueMap;
  12. import org.springframework.web.reactive.function.BodyInserters;
  13. import org.springframework.web.reactive.function.client.ClientResponse;
  14. import org.springframework.web.reactive.function.client.ExchangeStrategies;
  15. import org.springframework.web.reactive.function.client.WebClient;
  16. import com.fasterxml.jackson.core.type.TypeReference;
  17. import com.fasterxml.jackson.databind.ObjectMapper;
  18. import io.netty.channel.ChannelOption;
  19. import io.netty.handler.timeout.ReadTimeoutHandler;
  20. import reactor.core.publisher.Mono;
  21. import reactor.netty.http.client.HttpClient;
  22. /**
  23. * @Description webClient 客户端
  24. * @Author WGK
  25. * @Date 2023/11/15 10:39
  26. */
  27. public class HttpClientUtils {
  28. private static final Integer DEFAULT_CONNECT_TIMEOUT = 3000;
  29. private static final Integer DEFAULT_REQUEST_TIMEOUT = 10000;
  30. private static final Integer MAX_IN_MEMORY_SIZE = 100 * 1024 * 1024;
  31. /**
  32. * get请求解析成字符串
  33. *
  34. * @param url url
  35. * @return java.lang.String
  36. */
  37. public static ClientResponse getResponse(String url) {
  38. Mono<ClientResponse> resp = createWebClientWithConnectAndReadTimeOuts().get().uri(url).exchange();
  39. return resp.block();
  40. }
  41. /**
  42. * get请求,解析成对象
  43. *
  44. * @param url url
  45. * @param tClass class
  46. * @param headers 请求头
  47. * @return T
  48. */
  49. public static <T> T get(String url, Class<T> tClass, Map<String, String> headers) {
  50. Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().get().uri(url).headers(t -> t.setAll(headers))
  51. .retrieve().bodyToMono(tClass).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  52. return resp.block();
  53. }
  54. /**
  55. * get请求,解析成对象
  56. *
  57. * @param url url
  58. * @param headers 请求头
  59. * @return T
  60. */
  61. public static String get(String url, Map<String, String> headers) {
  62. Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().get().uri(url).headers(t -> t.setAll(headers))
  63. .retrieve().bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  64. return resp.block();
  65. }
  66. /**
  67. * get请求,解析成对象
  68. *
  69. * @param scheme 协议 http/https
  70. * @param host host
  71. * @param obj query params
  72. * @param headers 请求头
  73. * @return T
  74. */
  75. public static String get(String scheme, String host, String path, Object obj, Map<String, String> headers) {
  76. Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().get()
  77. .uri(uriBuilder -> uriBuilder.scheme(scheme).host(host).path(path).queryParams(getRequestParamMapByObj(obj))
  78. .build())
  79. .headers(t -> t.setAll(headers)).retrieve().bodyToMono(String.class)
  80. .timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  81. return resp.block();
  82. }
  83. /**
  84. * get请求,解析成对象
  85. *
  86. * @param url url
  87. * @param tClass class
  88. * @return T
  89. */
  90. public static <T> T get(String url, Object obj, Class<T> tClass) {
  91. Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().get()
  92. .uri(uriBuilder -> uriBuilder.path(url).queryParams(getRequestParamMapByObj(obj)).build()).retrieve()
  93. .bodyToMono(tClass).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  94. return resp.block();
  95. }
  96. /**
  97. * get请求,解析成对象
  98. *
  99. * @param url url
  100. * @param tClass class
  101. * @return T
  102. */
  103. public static <T> T get(String url, Class<T> tClass) {
  104. Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().get().uri(url).retrieve().bodyToMono(tClass)
  105. .timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  106. return resp.block();
  107. }
  108. /**
  109. * get请求解析成字符串
  110. *
  111. * @param url url
  112. * @return java.lang.String
  113. */
  114. public static String get(String url) {
  115. Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().get().uri(url).retrieve()
  116. .bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  117. return resp.block();
  118. }
  119. /**
  120. * post表单请求返回对象
  121. *
  122. * @param url url
  123. * @param params 请求参数
  124. * @param tClass 返回对象
  125. * @return T
  126. */
  127. public static <T> T post(String url, Map<String, String> params, Class<T> tClass) {
  128. MultiValueMap<String, String> formData = getRequestParamMap(params);
  129. Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
  130. .contentType(MediaType.APPLICATION_FORM_URLENCODED).body(BodyInserters.fromFormData(formData)).retrieve()
  131. .bodyToMono(tClass).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  132. return resp.block();
  133. }
  134. /**
  135. * post表单请求返回字符串
  136. *
  137. * @param url url
  138. * @param params 请求参数
  139. * @return java.lang.String
  140. */
  141. public static String post(String url, Map<String, String> params) {
  142. MultiValueMap<String, String> formData = getRequestParamMap(params);
  143. Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
  144. .contentType(MediaType.APPLICATION_FORM_URLENCODED).body(BodyInserters.fromFormData(formData)).retrieve()
  145. .bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  146. return resp.block();
  147. }
  148. /**
  149. * post json请求结果解析成对象
  150. *
  151. * @param url url
  152. * @param jsonBody 请求body,可以是对象或者是map
  153. * @param tClass 解析对象
  154. * @return T
  155. */
  156. public static <T> T postJson(String url, Object jsonBody, Class<T> tClass) {
  157. Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
  158. .contentType(MediaType.APPLICATION_JSON_UTF8).body(Mono.just(jsonBody), Object.class).retrieve()
  159. .bodyToMono(tClass).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  160. return resp.block();
  161. }
  162. /**
  163. * post json请求结果解析成对象
  164. *
  165. * @param url url
  166. * @param jsonBody 请求body,可以是对象或者是map
  167. * @param tClass 解析对象
  168. * @return T
  169. */
  170. public static <T> T postJson(String url, Map<String, String> headers, Object jsonBody, Class<T> tClass) {
  171. Mono<T> resp =
  172. createWebClientWithConnectAndReadTimeOuts().post().uri(url).contentType(MediaType.APPLICATION_JSON_UTF8)
  173. .headers(t -> t.setAll(headers)).body(Mono.just(jsonBody), Object.class).retrieve().bodyToMono(tClass)
  174. .timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  175. return resp.block();
  176. }
  177. /**
  178. * post json请求结果解析成字符串
  179. *
  180. * @param url url
  181. * @param jsonBody 请求body,可以是对象或者是map
  182. * @return java.lang.String
  183. */
  184. public static String postJson(String url, Object jsonBody) {
  185. Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
  186. .contentType(MediaType.APPLICATION_JSON_UTF8).body(Mono.just(jsonBody), Object.class).retrieve()
  187. .bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  188. return resp.block();
  189. }
  190. /**
  191. * post json请求结果解析成字符串
  192. *
  193. * @param url url
  194. * @param jsonBody 请求body,可以是对象或者是map
  195. * @return java.lang.String
  196. */
  197. public static String postJson(String url, Map<String, String> headers, Object jsonBody) {
  198. Mono<String> resp =
  199. createWebClientWithConnectAndReadTimeOuts().post().uri(url).contentType(MediaType.APPLICATION_JSON_UTF8)
  200. .headers(t -> t.setAll(headers)).body(Mono.just(jsonBody), Object.class).retrieve()
  201. .bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  202. return resp.block();
  203. }
  204. public static <T> T postRawJson(String url, String jsonBody, Class<T> tClass) {
  205. Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
  206. .contentType(MediaType.APPLICATION_JSON_UTF8).body(BodyInserters.fromObject(jsonBody)).retrieve()
  207. .bodyToMono(tClass).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  208. return resp.block();
  209. }
  210. public static String postRawJson(String url, String jsonBody) {
  211. Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
  212. .contentType(MediaType.APPLICATION_JSON_UTF8).body(BodyInserters.fromObject(jsonBody)).retrieve()
  213. .bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
  214. return resp.block();
  215. }
  216. private static WebClient createWebClientWithConnectAndReadTimeOuts() {
  217. // create reactor netty HTTP client
  218. HttpClient httpClient = HttpClient.create().tcpConfiguration(tcpClient -> {
  219. tcpClient = tcpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, DEFAULT_CONNECT_TIMEOUT);
  220. tcpClient = tcpClient.doOnConnected(
  221. conn -> conn.addHandlerLast(new ReadTimeoutHandler(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)));
  222. return tcpClient;
  223. });
  224. // create a client http connector using above http client
  225. ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
  226. // use this configured http connector to build the web client
  227. return WebClient.builder()
  228. .exchangeStrategies(ExchangeStrategies.builder()
  229. .codecs(
  230. clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs().maxInMemorySize(MAX_IN_MEMORY_SIZE))
  231. .build())
  232. .clientConnector(connector).build();
  233. }
  234. private static MultiValueMap<String, String> getRequestParamMap(Map<String, String> params) {
  235. MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
  236. for (Map.Entry<String, String> entry : params.entrySet()) {
  237. queryParams.add(entry.getKey(), entry.getValue());
  238. }
  239. return queryParams;
  240. }
  241. private static MultiValueMap<String, String> getRequestParamMapByObj(Object obj) {
  242. ObjectMapper objectMapper = new ObjectMapper();
  243. Map<String, Object> map = objectMapper.convertValue(obj, new TypeReference<Map<String, Object>>() {});
  244. MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
  245. for (Map.Entry<String, Object> entry : map.entrySet()) {
  246. if (Objects.isNull(entry.getValue())) {
  247. continue;
  248. }
  249. queryParams.add(entry.getKey(), String.valueOf(entry.getValue()));
  250. }
  251. return queryParams;
  252. }
  253. }