0


使用RestTemplate模拟postman(get/post请求)

前言

项目中有个模板的功能是可以模仿postman进行http请求。 之前使用过httpClient,这次就来试试看更加模板化的RestTemplate吧~

关于RestTemplate的教程网上有很多,但大多都是秉着授人以渔的心态写的,也就是说在实战方面写得并不是很详细。这次我就借着模块开发的机会,来分享一下我是怎么编写http请求工具类的吧。

首先,要使用RestTemplate的exchange方法作为整个工具类的基础,借助它的可自定义配置,我们可以实现 使用任意格式的请求参数 和 返回任意格式的结果。这对于一个工具类来说是非常重要的。

需要注意的是,在RestTemplate中使用post方式请求 + 使用formdata格式传递body参数时,不能使用Map,需要要使用MultiValueMap


实战环节

代码如下(示例):

  1. /**
  2. * RestTemplateUtils 【http请求工具类】
  3. * 1. sendGet() sendPost() 是正常http请求
  4. * <br>
  5. * 2. sendGetByByte() sendPostByByte() 是用来下载字节流的
  6. * <br>
  7. * 3. 支持的请求方式:<br>
  8. * <b>
  9. * post请求 -json传参<br>
  10. * post请求 -formData传参<br>
  11. * get请求 -占位符传参<br>
  12. * get请求 -url拼接<br>
  13. * </b>
  14. *
  15. * @author xurenyi
  16. * @since 2023/3/29 17:36
  17. **/
  18. public class RestTemplateUtils {
  19. private static Logger logger = LoggerFactory.getLogger("RestTemplateUtils");
  20. private volatile static RestTemplate restTemplate;
  21. /**
  22. * GET请求
  23. *
  24. * @param url
  25. * @param returnDataType 返回数据的格式 JSONObject|JSONArray.class|String.class|Map.class|ArrayList.class,可为空
  26. * @param requestHeaders 请求头,可为空
  27. * @param requestParams 求参数,可为空
  28. * @return 结果
  29. */
  30. public static Object sendGet(String url,
  31. @Nullable Class<?> returnDataType,
  32. @Nullable Map<String, Object> requestHeaders,
  33. @Nullable Map<String, Object> requestParams) {
  34. return httpRequest(url, HttpMethod.GET, requestHeaders, requestParams, null, returnDataType, JSONObject.class);
  35. }
  36. /**
  37. * POST请求
  38. *
  39. * @param url
  40. * @param returnDataType 返回数据的格式 JSONObject|JSONArray.class|String.class|Map.class|ArrayList.class,可为空
  41. * @param requestHeaders 请求头,可为空
  42. * @param requestParams 请求参数,可为空
  43. * @param requestBody 请求体,可为空
  44. * @param sendDataType 请求体格式 json|jsonArray
  45. * @return 结果
  46. */
  47. public static Object sendPost(String url,
  48. @Nullable Class<?> returnDataType,
  49. @Nullable Map<String, Object> requestHeaders,
  50. @Nullable Map<String, Object> requestParams,
  51. @Nullable String requestBody,
  52. Class<?> sendDataType) {
  53. return httpRequest(url, HttpMethod.POST, requestHeaders, requestParams, requestBody, returnDataType, sendDataType);
  54. }
  55. /**
  56. * POST请求 字节流
  57. *
  58. * @param url
  59. * @param response http响应消息,可为空
  60. * @param requestHeaders 请求头,可为空
  61. * @param requestParams 请求参数,可为空
  62. * @param requestBody 请求体,可为空
  63. * @param sendDataType 请求体格式 json|jsonArray
  64. **/
  65. public static void sendPostByByte(String url, HttpServletResponse response,
  66. @Nullable Map<String, Object> requestHeaders,
  67. @Nullable Map<String, Object> requestParams,
  68. @Nullable String requestBody,
  69. Class<?> sendDataType) {
  70. download(url, HttpMethod.POST, requestHeaders, requestParams, requestBody, response, false, sendDataType);
  71. }
  72. /**
  73. * GET请求 字节流
  74. *
  75. * @param url
  76. * @param response http响应消息,可为空
  77. * @param requestHeaders 请求头,可为空
  78. * @param requestParams 请求参数,可为空
  79. **/
  80. public static void sendGetByByte(String url, HttpServletResponse response,
  81. @Nullable Map<String, Object> requestHeaders,
  82. @Nullable Map<String, Object> requestParams) {
  83. download(url, HttpMethod.GET, requestHeaders, requestParams, null, response, false, JSONObject.class);
  84. }
  85. /**
  86. * 发送http请求
  87. *
  88. * @param url
  89. * @param method
  90. * @param requestHeaders
  91. * @param requestParams
  92. * @param requestBody
  93. * @param returnDataType
  94. * @return
  95. */
  96. public static <T> Object httpRequest(String url, HttpMethod method,
  97. @Nullable Map<String, Object> requestHeaders,
  98. @Nullable Map<String, Object> requestParams,
  99. @Nullable String requestBody,
  100. @Nullable Class<?> returnDataType,
  101. Class<?> sendDataType) {
  102. Map<String, Object> params = new HashMap<>();
  103. HttpHeaders headers = new HttpHeaders();
  104. // 1. post请求 -json传参
  105. // 2. post请求 -formData传参
  106. // 3. get请求 -占位符传参
  107. // 4. get请求 -url拼接
  108. // 第一步 构建httpEntity
  109. HttpEntity<?> entity = buildHttpEntity(sendDataType, method, requestHeaders, requestParams, requestBody, params, headers);
  110. // 第二步 单例调用restTemplate
  111. RestTemplate restTemplate = getSingleRestTemplate();
  112. // 第三步 初始化一个返回值
  113. Object r = null;
  114. // 第四步 执行http请求,并根据情况给返回值赋值
  115. try {
  116. Class<?> resultClass = String.class;
  117. if (returnDataType != null) {
  118. resultClass = returnDataType;
  119. r = handleHttpRequest(restTemplate, resultClass, url, method, params, entity);
  120. } else {
  121. handleHttpRequest(restTemplate, resultClass, url, method, params, entity);
  122. }
  123. } catch (RestClientException e) {
  124. logger.error("远程调用接口异常{}", e);
  125. }
  126. return r;
  127. }
  128. /**
  129. * 下载
  130. *
  131. * @param url
  132. * @param method
  133. * @param requestHeaders
  134. * @param requestParams
  135. * @param requestBody
  136. * @param response
  137. * @param isRespBodyOnly 是否是只需要响应体,默认true,true:只需要响应体 false:同时返回响应状态 响应头 响应体
  138. */
  139. public static void download(String url, HttpMethod method,
  140. @Nullable Map<String, Object> requestHeaders,
  141. @Nullable Map<String, Object> requestParams,
  142. @Nullable String requestBody,
  143. HttpServletResponse response,
  144. @Nullable Boolean isRespBodyOnly,
  145. Class<?> sendDataType) {
  146. if (Objects.isNull(isRespBodyOnly)) {
  147. isRespBodyOnly = true;
  148. }
  149. HttpHeaders headers = new HttpHeaders();
  150. Map<String, Object> params = new HashMap<>();
  151. // 第一步 构建httpEntity
  152. HttpEntity<?> entity = buildHttpEntity(sendDataType, method, requestHeaders, requestParams, requestBody, params, headers);
  153. // 第二步 单例调用restTemplate
  154. RestTemplate restTemplate = getSingleRestTemplate();
  155. // 第三步 执行http请求,并返回字节流
  156. handleHttpRequest(restTemplate, url, method, response, isRespBodyOnly, params, entity);
  157. }
  158. /**
  159. * 构建httpEntity
  160. *
  161. * @param method
  162. * @param requestHeaders
  163. * @param requestParams
  164. * @param requestBody
  165. * @param params
  166. * @param headers
  167. * @return
  168. */
  169. private static HttpEntity<?> buildHttpEntity(Class<?> sendDataType, HttpMethod method, Map<String, Object> requestHeaders, Map<String, Object> requestParams, String requestBody, Map<String, Object> params, HttpHeaders headers) {
  170. //1.设置请求参数
  171. if (requestParams != null && !requestParams.isEmpty()) {
  172. Iterator<Map.Entry<String, Object>> paramsIterator = requestParams.entrySet().iterator();
  173. Map.Entry<String, Object> nextParam = null;
  174. while (paramsIterator.hasNext()) {
  175. nextParam = paramsIterator.next();
  176. params.put(nextParam.getKey(), nextParam.getValue());
  177. }
  178. }
  179. //2.设置请求头
  180. if (requestHeaders != null && !requestHeaders.isEmpty()) {
  181. Iterator<Map.Entry<String, Object>> headersIterator = requestHeaders.entrySet().iterator();
  182. Map.Entry<String, Object> nextHeader = null;
  183. while (headersIterator.hasNext()) {
  184. nextHeader = headersIterator.next();
  185. headers.add(nextHeader.getKey(), String.valueOf(nextHeader.getValue()));
  186. }
  187. }
  188. //3.设置请求体
  189. //4.请求体 请求头封装到HttpEntity
  190. String contentType = String.valueOf(requestHeaders.get(EtlHttpRequestConstant.CONTENT_TYPE));
  191. if (requestBody != null && !requestBody.isEmpty()) {
  192. if (sendDataType == null || sendDataType.equals(JSONObject.class)) {
  193. Map<String, Object> requestBodyMap = JSONObject.parseObject(requestBody, Map.class);
  194. Map bodyMap;
  195. if (MediaType.APPLICATION_JSON_VALUE.equals(contentType) || HttpMethod.GET.equals(method)) {
  196. bodyMap = setEntityBody(Map.class, requestBodyMap);
  197. } else {
  198. bodyMap = setEntityBody(LinkedMultiValueMap.class, requestBodyMap);
  199. }
  200. return new HttpEntity<>(bodyMap, headers);
  201. } else if (sendDataType.equals(JSONArray.class)) {
  202. List<Map> requestBodyMapList = JSON.parseArray(requestBody, Map.class);
  203. List<Map> bodyMapList = new ArrayList<>();
  204. if (MediaType.APPLICATION_JSON_VALUE.equals(contentType) || HttpMethod.GET.equals(method)) {
  205. requestBodyMapList.forEach(i -> bodyMapList.add(setEntityBody(Map.class, i)));
  206. } else {
  207. requestBodyMapList.forEach(i -> bodyMapList.add(setEntityBody(LinkedMultiValueMap.class, i)));
  208. }
  209. return new HttpEntity<>(bodyMapList, headers);
  210. } else if (sendDataType.equals(String.class)) {
  211. return new HttpEntity<>(requestBody, headers);
  212. }
  213. }
  214. // todo 如果是其他情况,则返回null
  215. return new HttpEntity<>(null, headers);
  216. }
  217. /**
  218. * 请求http请求
  219. *
  220. * @param restTemplate
  221. * @param typeClass
  222. * @param url
  223. * @param method
  224. * @param params
  225. * @param entity
  226. * @param <T>
  227. * @return
  228. */
  229. private static <T> T handleHttpRequest(RestTemplate restTemplate, Class<T> typeClass, String url, HttpMethod method, Map<String, Object> params, HttpEntity<?> entity) {
  230. ResponseEntity<T> exchange = restTemplate.exchange(url, method, entity, typeClass, params);
  231. return typeClass.cast(exchange.getBody());
  232. }
  233. /**
  234. * 处理http请求(字节流)
  235. *
  236. * @param restTemplate
  237. * @param url
  238. * @param method
  239. * @param response
  240. * @param isRespBodyOnly
  241. * @param params
  242. * @param entity
  243. */
  244. private static void handleHttpRequest(RestTemplate restTemplate, String url, HttpMethod method, HttpServletResponse response, Boolean isRespBodyOnly, Map<String, Object> params, HttpEntity<?> entity) {
  245. BufferedOutputStream bos = null;
  246. try {
  247. ResponseEntity<byte[]> exchange = restTemplate.exchange(url, method, entity, byte[].class, params);
  248. if (!isRespBodyOnly && response != null) {
  249. setResponseDetails(response, exchange);
  250. }
  251. // FIXME: 2023/3/29 by.xurenyi 修改下载文件流的格式,此处有些小问题,暂定使用原接口的文件格式~~~
  252. // response.reset();
  253. // response.setContentType("pdf/plain");
  254. // response.setContentType("application/octet-stream;charset=UTF-8");
  255. // response.setHeader("Content-Type", "application/octet-stream;charset=UTF-8");
  256. // response.setHeader("Content-Disposition", "attachment; filename=" + "test" + ".pdf");
  257. //响应体
  258. ServletOutputStream os = response.getOutputStream();
  259. bos = new BufferedOutputStream(os);
  260. byte[] buf = exchange.getBody();
  261. bos.write(buf);
  262. bos.flush();
  263. } catch (IOException e) {
  264. logger.error("RestTemplateUtils获取接口二进制流异常");
  265. } catch (RestClientException e) {
  266. logger.error("远程调用接口异常{}", e);
  267. } finally {
  268. try {
  269. bos.close();
  270. } catch (IOException e) {
  271. logger.error("RestTemplateUtils流关闭异常");
  272. }
  273. }
  274. }
  275. /**
  276. * 设置http响应详情
  277. *
  278. * @param response
  279. * @param exchange
  280. * @param <T>
  281. */
  282. private static <T> void setResponseDetails(HttpServletResponse response, ResponseEntity<T> exchange) {
  283. //响应状态码
  284. response.setStatus(exchange.getStatusCodeValue());
  285. //响应头,可能存在一个key对应多个value,本方法中会将同名header合并
  286. HttpHeaders resHeaders = exchange.getHeaders();
  287. Iterator<Entry<String, List<String>>> resHeadersIterator = resHeaders.entrySet().iterator();
  288. while (resHeadersIterator.hasNext()) {
  289. Entry<String, List<String>> headersNext = resHeadersIterator.next();
  290. response.setHeader(headersNext.getKey(), headersNext.getValue().toString());
  291. }
  292. }
  293. /**
  294. * 设置entity
  295. *
  296. * @param beanClass
  297. * @param requestBody
  298. * @return
  299. */
  300. private static Map setEntityBody(Class<? extends Map> beanClass, Map<String, Object> requestBody) {
  301. Object entityBody;
  302. Iterator<Entry<String, Object>> bodyIterator = requestBody.entrySet().iterator();
  303. Entry<String, Object> bodyNext;
  304. if (beanClass.equals(MultiValueMap.class) || beanClass.equals(LinkedMultiValueMap.class)) {
  305. MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
  306. while (bodyIterator.hasNext()) {
  307. bodyNext = bodyIterator.next();
  308. map.add(bodyNext.getKey(), bodyNext.getValue());
  309. }
  310. entityBody = map;
  311. } else if (beanClass.equals(Map.class)) {
  312. Map<String, Object> map = new HashMap<>();
  313. while (bodyIterator.hasNext()) {
  314. bodyNext = bodyIterator.next();
  315. map.put(bodyNext.getKey(), bodyNext.getValue());
  316. }
  317. entityBody = map;
  318. } else {
  319. Map<String, Object> map = new HashMap<>();
  320. while (bodyIterator.hasNext()) {
  321. bodyNext = bodyIterator.next();
  322. map.put(bodyNext.getKey(), bodyNext.getValue());
  323. }
  324. entityBody = map;
  325. }
  326. return beanClass.cast(entityBody);
  327. }
  328. /**
  329. * RestTemplate 单例 懒汉 双检锁
  330. **/
  331. public static RestTemplate getSingleRestTemplate() {
  332. if (restTemplate == null) {
  333. synchronized (RestTemplateUtils.class) {
  334. if (restTemplate == null) {
  335. restTemplate = new RestTemplate();
  336. }
  337. }
  338. }
  339. return restTemplate;
  340. }
  341. }
标签: java http

本文转载自: https://blog.csdn.net/m0_54892309/article/details/129862751
版权归原作者 醒盼梦惜忆甚悠 所有, 如有侵权,请联系我们删除。

“使用RestTemplate模拟postman(get/post请求)”的评论:

还没有评论