小熙前端时间忙于分布式系统的开发,在远程调用的时候,有用到restTempalte的使用自己封装了一个使用案例。后来,由于系统慢慢的整合一些东西,restTempalte埋的坑太多,所以后续有去用到feign了,此案例还是建议相对自己的项目去抉择吧。
有一些特殊的依赖,标注下(也可以不导入,可以手动实现相关,不过比较麻烦)
糊涂工具坐标
cn.hutool
hutool-all
5.0.7
谷歌工具坐标
com.google.code.gson
gson
2.8.5
分页工具类(可以替换成自己项目环境的,小熙替换了自己项目的写了一个简易的)
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 {
@ApiModelProperty(value = "当前页")
private Integer currentPage = 1;
@ApiModelProperty(value = "展示数量")
private Integer pageSize = 10;
@ApiModelProperty(value = "总记录数")
private Long count = 0L;
@ApiModelProperty(value = "返回数据")
private List 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
* @param
* @return
*/
public static T requestGet(String appId, String apiUrl, R requestDate, Class responseBeanClass, RestTemplate restTemplate){
return restTemplate.getForObject(urlCreat(appId, apiUrl),responseBeanClass,requestDate);
}
/**
* Post请求
* @param appId
* @param apiUrl
* @param requestDate
* @param responseBeanClass
* @param restTemplate
* @param
* @param
* @return 返回Bean
*/
public static T requestBeanPost(String appId, String apiUrl, R requestDate, Class responseBeanClass, RestTemplate restTemplate){
return requestMethodBodyBean(appId, apiUrl, requestDate, responseBeanClass, restTemplate, HttpMethod.POST);
}
/**
* Post请求
* @param appId
* @param apiUrl
* @param requestDate
* @param responseBeanClass
* @param restTemplate
* @param
* @param
* @return 返回List
*/
public static List requestBeanListPost(String appId, String apiUrl, R requestDate, Class 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
* @param
* @return 返回Page>
*/
public static PageVO requestBeanListPageVoPost(String appId, String apiUrl, R requestDate, Class responseBeanClass, RestTemplate restTemplate){
Map responseMapData = null;
Object responseData = requestMethodBody(appId, apiUrl, requestDate, restTemplate, HttpMethod.POST);
if (responseData == null) {
return null;
}
try {
responseMapData = (HashMap) 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 responseDateList = getResponseDateList(data, responseBeanClass);
return new PageVO(currentPage, pageSize, (long)count, responseDateList);
}
/**
* Post请求
* @param appId
* @param apiUrl
* @param requestDate
* @param restTemplate
* @param
* @return 返回List(String)
*/
public static List 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) responseDate;
}else if (responseDate instanceof Set) {
return new ArrayList((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) responseDate;
}else if (requestDate instanceof AbstractCollection) {
return (List) 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
* @return 返回bean
*/
public static T requestGet(String appId, String apiUrl, Class responseBeanClass, RestTemplate restTemplate){
return restTemplate.getForObject(urlCreat(appId, apiUrl),responseBeanClass);
}
/**
* Post请求 无参
* @param appId
* @param apiUrl
* @param responseBeanClass
* @param restTemplate
* @param
* @return 返回bean
*/
public static T requestBeanPost(String appId, String apiUrl, Class 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
* @param
* @return
*/
protected static T requestMethodBodyBean(String appId, String apiUrl, R requestDate, Class responseBeanClass, RestTemplate restTemplate, HttpMethod httpMethod){
Object responseDate = requestMethodBody(appId, apiUrl,requestDate,restTemplate,httpMethod);
if (responseDate == null) {
return null;
}
Map data = (Map) 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
* @param
* @return
*/
protected static List requestMethodBodyBeanList(List
小熙写一段代码介绍下基本使用,其他方法同理:
服务调用方
// 小熙列举其中之一的方法举例,其他同理
// 第一个参数是服务id(服务名称),第二个参数是服务内的访问路径,第三个参数是请求参数对象,第四个参数是返回类型的class,第五个参数是restTemplate(依赖注入后入参)
List userList = RestTemplateUtil.requestBeanListPost("user-center", "/userController/selectUserByCondition", new SearchUserVO(), User.class, restTemplate);
服务提供方
@PostMapping(value = "/selectUserByCondition")
@ApiOperation(value = "通过条件查询用户,供远程调用")
public ResponseEntity> selectUserByCondition(SearchUserVO searchUserVO){
List userList = userService.list(Wrappers.lambdaQuery()
.like(StringUtils.isNotEmpty(searchUserVO.getName()), User::getName, searchUserVO.getName())
.eq(User::getAge, searchUserVO.getAge()));
return new ResponseEntity<>(userList, HttpStatus.OK);
}
小熙写的是根据目前使用到的,大部分场景应该可以了,如果有其他场景可以拓展,技术有限,大家可以发表些见解,感谢指正。