欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

restTemplate封装工具类

程序员文章站 2022-03-26 20:25:46
一. 前言 :小熙前端时间忙于分布式系统的开发,在远程调用的时候,有用到restTempalte的使用自己封装了一个使用案例。后来,由于系统慢慢的整合一些东西,restTempalte埋的坑太多,所以后续的有去用到feign,此案例还是建议相对自己的项目去抉择吧。二. 视图:展示图:三. 依赖 :有一些特殊的依赖,标注下(也可以不导入,可以手动实现相关,不过比较麻烦)糊涂工具坐标 ...

一. 前言 :

小熙前端时间忙于分布式系统的开发,在远程调用的时候,有用到restTempalte的使用自己封装了一个使用案例。后来,由于系统慢慢的整合一些东西,restTempalte埋的坑太多,所以后续有去用到feign了,此案例还是建议相对自己的项目去抉择吧。

二. 视图:

展示图:
restTemplate封装工具类

三. 依赖 :

有一些特殊的依赖,标注下(也可以不导入,可以手动实现相关,不过比较麻烦)

  1. 糊涂工具坐标

    	    <!-- 糊涂工具类 -->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.0.7</version>
            </dependency>
    
  2. 谷歌工具坐标

    		<!--谷歌工具类-->
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.8.5</version>
            </dependency>
    
  3. 分页工具类(可以替换成自己项目环境的,小熙替换了自己项目的写了一个简易的)

    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);
    
    }
    
    
  4. 响应封装工具

     小熙替换了自己项目的,替换成了 springMVC 的 ResponseEntity,也可以替换成自己项目的更适合项目环境
    

四. 代码 :

  1. 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);
        }
    
    }
    
    
  2. 抽取封装类:

    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;
        }
    
    }
    
    

五. 示例:

小熙写一段代码介绍下基本使用,其他方法同理:

  1. 服务调用方

    // 小熙列举其中之一的方法举例,其他同理
    // 第一个参数是服务id(服务名称),第二个参数是服务内的访问路径,第三个参数是请求参数对象,第四个参数是返回类型的class,第五个参数是restTemplate(依赖注入后入参)
    List<User> userList = RestTemplateUtil.requestBeanListPost("user-center", "/userController/selectUserByCondition", new SearchUserVO(), User.class, restTemplate);
    
  2. 服务提供方

    @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