restTemplate封装工具类
程序员文章站
2022-06-28 18:41:45
一. 前言 :小熙前端时间忙于分布式系统的开发,在远程调用的时候,有用到restTempalte的使用自己封装了一个使用案例。后来,由于系统慢慢的整合一些东西,restTempalte埋的坑太多,所以后续的有去用到feign,此案例还是建议相对自己的项目去抉择吧。二. 视图:展示图:三. 依赖 :有一些特殊的依赖,标注下(也可以不导入,可以手动实现相关,不过比较麻烦)糊涂工具坐标 ...
一. 前言 :
小熙前端时间忙于分布式系统的开发,在远程调用的时候,有用到restTempalte的使用自己封装了一个使用案例。后来,由于系统慢慢的整合一些东西,restTempalte埋的坑太多,所以后续有去用到feign了,此案例还是建议相对自己的项目去抉择吧。
二. 视图:
展示图:
三. 依赖 :
有一些特殊的依赖,标注下(也可以不导入,可以手动实现相关,不过比较麻烦)
-
糊涂工具坐标
<!-- 糊涂工具类 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.0.7</version> </dependency>
-
谷歌工具坐标
<!--谷歌工具类--> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency>
-
分页工具类(可以替换成自己项目环境的,小熙替换了自己项目的写了一个简易的)
package com.chengxi.datalom.utils.rest; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import java.util.ArrayList; import java.util.List; /** * @author chengxi * @date 2020/7/13 17:21 */ @Data @AllArgsConstructor public class PageVO<T> { @ApiModelProperty(value = "当前页") private Integer currentPage = 1; @ApiModelProperty(value = "展示数量") private Integer pageSize = 10; @ApiModelProperty(value = "总记录数") private Long count = 0L; @ApiModelProperty(value = "返回数据") private List<T> data = new ArrayList<>(10); }
-
响应封装工具
小熙替换了自己项目的,替换成了 springMVC 的 ResponseEntity,也可以替换成自己项目的更适合项目环境
四. 代码 :
-
restTemplate工具类:
package com.chengxi.datalom.utils.rest; import com.baomidou.mybatisplus.extension.api.R; import com.chengxi.datalom.po.User; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import java.util.*; /** * 程熙cjp:https://blog.csdn.net/weixin_41133233 * * resetTemplate自定义请求工具类 * restTemplate 需要请求方注入,因为来自不同服务所以要携带一些自己的信息 * 远程调用默认返回本项目中自定的ResponseVO类 * * @author chengxi * @date 2020/5/30 21:00 */ @Slf4j @Component public class RestTemplateUtil extends AbstractExtractionRestUtil { /** * Get请求a * get请求如果需要携带body传输,请自定义一a个factory,扩展HttpComponentsClientHttpRequestFactory,并在RestTemplateConfig中指定此拓展 * @param appId 服务id * @param apiUrl 访问路径 * @param requestDate 请求参数 * @param responseBeanClass 返回bean的类型 * @param restTemplate 注入的RestTemplate * @param <T> * @param <R> * @return */ public static <T,R extends Object> T requestGet(String appId, String apiUrl, R requestDate, Class<T> responseBeanClass, RestTemplate restTemplate){ return restTemplate.getForObject(urlCreat(appId, apiUrl),responseBeanClass,requestDate); } /** * Post请求 * @param appId * @param apiUrl * @param requestDate * @param responseBeanClass * @param restTemplate * @param <T> * @param <R> * @return 返回Bean */ public static <T,R> T requestBeanPost(String appId, String apiUrl, R requestDate, Class<T> responseBeanClass, RestTemplate restTemplate){ return requestMethodBodyBean(appId, apiUrl, requestDate, responseBeanClass, restTemplate, HttpMethod.POST); } /** * Post请求 * @param appId * @param apiUrl * @param requestDate * @param responseBeanClass * @param restTemplate * @param <T> * @param <R> * @return 返回List<Bean> */ public static <T,R> List<T> requestBeanListPost(String appId, String apiUrl, R requestDate, Class<T> responseBeanClass, RestTemplate restTemplate){ Object responseDate = requestMethodBody(appId, apiUrl, requestDate, restTemplate, HttpMethod.POST); return getResponseDateList(responseDate, responseBeanClass); } /** * Post请求 * @param appId * @param apiUrl * @param requestDate * @param responseBeanClass * @param restTemplate * @param <T> * @param <R> * @return 返回Page<List<Bean>> */ public static <T,R> PageVO<T> requestBeanListPageVoPost(String appId, String apiUrl, R requestDate, Class<T> responseBeanClass, RestTemplate restTemplate){ Map<String, Object> responseMapData = null; try { Object responseData = requestMethodBody(appId, apiUrl, requestDate, restTemplate, HttpMethod.POST); if (responseData == null) { return null; } responseMapData = (HashMap<String, Object>) responseData; } catch (Exception e) { e.printStackTrace(); log.error("类型转换异常, 分页响应数据转换:{}", e); throw new ClassCastException("类型转换异常: 分页响应数据转换"); } Object data = responseMapData.get("data"); Integer currentPage = (Integer)responseMapData.get("currentPage"); Integer pageSize = (Integer)responseMapData.get("pageSize"); int count = (int)responseMapData.get("count"); List<T> responseDateList = getResponseDateList(data, responseBeanClass); return new PageVO<T>(currentPage, pageSize, (long)count, responseDateList); } /** * Post请求 * @param appId * @param apiUrl * @param requestDate * @param restTemplate * @param <R> * @return 返回List(String) */ public static <R> List<String> requestStringListPost(String appId, String apiUrl, R requestDate, RestTemplate restTemplate){ Object responseDate = requestMethodBody(appId, apiUrl, requestDate, restTemplate, HttpMethod.POST); if (responseDate == null) { return null; } try { if (responseDate instanceof List) { return (List<String>) responseDate; }else if (responseDate instanceof Set) { return new ArrayList<String>((Set)responseDate); }else if (responseDate instanceof String[]) { return Arrays.asList((String[]) responseDate); }else if (responseDate instanceof String) { return Lists.newArrayList((String) responseDate); }else if (requestDate instanceof Queue) { return (List<String>) responseDate; }else if (requestDate instanceof AbstractCollection) { return (List<String>) responseDate; } } catch (ClassCastException e) { e.printStackTrace(); log.error("类型转换异常,返回值转换为String类型异常:{}", e); throw new ClassCastException("类型转换异常,返回值转换为String类型异常"); } throw new ClassCastException("返回数据类型不是String"); } /** * Get请求 无参 * @param appId * @param apiUrl * @param responseBeanClass * @param restTemplate * @param <T> * @return 返回bean */ public static <T> T requestGet(String appId, String apiUrl, Class<T> responseBeanClass, RestTemplate restTemplate){ return restTemplate.getForObject(urlCreat(appId, apiUrl),responseBeanClass); } /** * Post请求 无参 * @param appId * @param apiUrl * @param responseBeanClass * @param restTemplate * @param <T> * @return 返回bean */ public static <T> T requestBeanPost(String appId, String apiUrl, Class<T> responseBeanClass, RestTemplate restTemplate){ return requestMethodBodyBean(appId, apiUrl, null, responseBeanClass, restTemplate, HttpMethod.POST); } }
-
抽取封装类:
package com.chengxi.datalom.utils.rest; import cn.hutool.core.bean.BeanUtil; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpMethod; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import java.net.URI; import java.util.*; import java.util.stream.Collectors; /** * 依赖方法封装 * * @author chengxi * @date 2020/5/30 21:00 */ @Slf4j public abstract class AbstractExtractionRestUtil { /** * 抽取请求bean * @param appId * @param apiUrl * @param requestDate * @param responseBeanClass * @param restTemplate * @param httpMethod * @param <T> * @param <R> * @return */ protected static <T,R> T requestMethodBodyBean(String appId, String apiUrl, R requestDate, Class<T> responseBeanClass, RestTemplate restTemplate, HttpMethod httpMethod){ Object responseDate = requestMethodBody(appId, apiUrl,requestDate,restTemplate,httpMethod); if (responseDate == null) { return null; } Map<String, Object> data = (Map<String, Object>) responseDate; T responseInfoBean = null; try { responseInfoBean = BeanUtil.mapToBean(data, responseBeanClass, false); } catch (Exception e) { e.printStackTrace(); log.error("类型转换异常,map投射Bean异常:{}", e); throw new ClassCastException("类型转换异常,map投射Bean异常"); } return responseInfoBean; } /** * 抽取请求beanList * @param responseDateList * @param responseBeanClass * @param <T> * @param <R> * @return */ protected static <T,R> List<T> requestMethodBodyBeanList(List<Object> responseDateList, Class<T> responseBeanClass) { try { return responseDateList.stream() .map(m -> { Map<String, Object> data = (Map<String, Object>) m; return BeanUtil.mapToBean(data, responseBeanClass, false); }).collect(Collectors.toList()); } catch (Exception e) { e.printStackTrace(); log.error("类型转换异常,map投射Bean异常:{}", e); throw new ClassCastException("类型转换异常,map投射Bean异常"); } } /** * 抽取请求body * @param appId * @param apiUrl * @param requestDate * @param restTemplate * @param httpMethod * @param <R> * @return */ protected static <R> Object requestMethodBody(String appId, String apiUrl, R requestDate, RestTemplate restTemplate, HttpMethod httpMethod){ String url = urlCreat(appId, apiUrl); RequestEntity<R> requestEntity = null; if (requestDate == null) { requestEntity = new RequestEntity<>(httpMethod, URI.create(url)); }else { requestEntity = new RequestEntity<>(requestDate, httpMethod, URI.create(url)); } // 这里的object可以替换成自己封装的返回类(更符合项目环境),小熙分享时是把项目中的替换成了object ResponseEntity<Object> exchange = null; try { exchange = restTemplate.exchange(requestEntity, Object.class); }catch (HttpClientErrorException e){ e.getResponseBodyAsString(); log.error("HttpClientErrorException:{}", e); throw new RestClientException(e.getResponseBodyAsString()); }catch (RestClientException e) { e.printStackTrace(); log.error("RestTemplate远程调用请求异常:{}", e); throw new RestClientException("RestTemplate远程调用请求异常"); } if (exchange == null) { log.info("exchange == null"); return null; }else if (exchange.getBody() == null) { log.info("exchange.getBody() == null"); return null; } return exchange.getBody(); } /** * 抽取响应体的集合 * @param responseDate * @param responseBeanClass * @param <T> * @return */ protected static<T> List<T> getResponseDateList(Object responseDate, Class<T> responseBeanClass){ if (responseDate == null) { return null; } if (responseDate instanceof List) { List<Object> responseDateList = (List<Object>) responseDate; return requestMethodBodyBeanList(responseDateList, responseBeanClass); }else if (responseDate instanceof Set) { Set<Object> responseDateSet = (Set<Object>) responseDate; List<Object> responseDateList = Lists.newArrayList(responseDateSet); return requestMethodBodyBeanList(responseDateList, responseBeanClass); } else if (responseDate.getClass().isArray()) { List<Object> responseDateList = Arrays.asList(responseDate); return requestMethodBodyBeanList(responseDateList, responseBeanClass); } throw new ClassCastException("返回类型不是单链集合"); } /** * 创建Url * @param appId * @param apiUrl * @return */ protected static String urlCreat(String appId, String apiUrl){ return "http://" + appId + apiUrl; } }
五. 示例:
小熙写一段代码介绍下基本使用,其他方法同理:
-
服务调用方
// 小熙列举其中之一的方法举例,其他同理 // 第一个参数是服务id(服务名称),第二个参数是服务内的访问路径,第三个参数是请求参数对象,第四个参数是返回类型的class,第五个参数是restTemplate(依赖注入后入参) List<User> userList = RestTemplateUtil.requestBeanListPost("user-center", "/userController/selectUserByCondition", new SearchUserVO(), User.class, restTemplate);
-
服务提供方
@PostMapping(value = "/selectUserByCondition") @ApiOperation(value = "通过条件查询用户,供远程调用") public ResponseEntity<List<User>> selectUserByCondition(SearchUserVO searchUserVO){ List<User> userList = userService.list(Wrappers.<User>lambdaQuery() .like(StringUtils.isNotEmpty(searchUserVO.getName()), User::getName, searchUserVO.getName()) .eq(User::getAge, searchUserVO.getAge())); return new ResponseEntity<>(userList, HttpStatus.OK); }
六. 后语:
小熙写的是根据目前使用到的,大部分场景应该可以了,如果有其他场景可以拓展,技术有限,大家可以发表些见解,感谢指正。
本文地址:https://blog.csdn.net/weixin_41133233/article/details/107340941
上一篇: NIO的缓冲区原理
下一篇: 03-django模型(1)