1 简介
比如商城系统,有一个订单服务,有一个中户中心服务,在订单详情中要根据userid获取订单创建人的昵称可以如下这样写:
java
@Trans(type = TransType.RPC,targetClassName = "com.fhs.ucenter.pojo.User",fields = "userName",serviceName = "ucenter")
private String createUserId;
2 字典如何处理
推荐将字典数据放到redis中去,详情使用见缓存相关说明章节 和 字典处理章节
3 权限控制
推荐在网关通过过滤器拦截/easyTrans/proxy开头的所有请求,解决前段能直接调用接口的问题。
推荐自定义resttemplate来给header加token配合拦截器的方式做校验
如果是多个团队共同开发一个项目,推荐配置 easy-trans.is-enable-custom-rpc=true,然后哪个PO给其他微服务做翻译用手动标记@RpcTrans注解 注意:@RpcTrans注解 从 3.0.1 和 2.2.12 版本开始提供
4 原理讲解(出了坑请看这里)
我们是通过一个控制器来暴漏接口给消费者调用,所以一定要保证服务A调用服务B的/easyTrans/proxy/*可以调用通。
代码如下(不同版本的代码可能不同,原理类似):
java
@RestController
@RequestMapping("/easyTrans/proxy")
public class TransProxyController {
private SimpleTransService.SimpleTransDiver simpleTransDiver;
/**
* findByIds
*
* @param targetClass 目标类
*/
@PostMapping("/{targetClass}/findByIds")
public List findByIds(@PathVariable("targetClass") String targetClass, @RequestBody FindByIdsQueryPayload payload) throws ClassNotFoundException {
Assert.notNull(targetClass, "targetClass 不可为空");
return simpleTransDiver.findByIds(payload.getIds(), (Class<? extends VO>) Class.forName(targetClass)).stream().map(vo -> {
try {
return vo2BasicVO(vo);
} catch (IllegalAccessException e) {
return null;
}
}).collect(Collectors.toList());
}
/**
* 根据id查询
*
* @param targetClass 目标类
*/
@GetMapping("/{targetClass}/findById/{id}")
public Object findByIds(@PathVariable("targetClass") String targetClass, @PathVariable("id") String id) throws ClassNotFoundException, IllegalAccessException {
Assert.notNull(targetClass, "targetClass 不可为空");
Assert.notNull(targetClass, "id 不可为空");
return vo2BasicVO(simpleTransDiver.findById(id, (Class<? extends VO>) Class.forName(targetClass)));
}
}
然后通过restTemplate进行调用,如果进行服务间调用认证请自己注入一个restTemplate,因为我们的restTemplate是这么写的:
java
@Bean
@LoadBalanced
@ConditionalOnMissingBean(RestTemplate.class)//如果你自己注入了,这个就不起作用就会用你自己注入的
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
然后RpcTransService是这么写的:
java
public class RpcTransService extends SimpleTransService {
private RestTemplate restTemplate;
@Override
public List<? extends VO> findByIds(List<String> ids, Trans tempTrans) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("ids", ids);
//执行远程调用
try {
String respJson = restTemplate.postForObject("http://" + tempTrans.serviceName()
+ "/easyTrans/proxy/" + tempTrans.targetClassName() + "/findByIds", paramMap, String.class);
return JSONArray.parseArray(respJson, BasicVO.class);
} catch (Exception e) {
log.error("trans service执行RPC Trans 远程调用错误:" + tempTrans.serviceName(), e);
}
return new ArrayList<>();
}
@Override
public VO findById(String id, Trans tempTrans) {
//执行远程调用
try {
return restTemplate.getForObject("http://" + tempTrans.serviceName()
+ "/easyTrans/proxy/" + tempTrans.targetClassName() + "/findById/" + id, BasicVO.class);
} catch (Exception e) {
log.error("trans service执行RPC Trans 远程调用错误:" + tempTrans.serviceName(), e);
}
return null;
}
}
以上就是RPC Trans实现的大部分代码了,有了坑一般就是权限框架拦截的问题,排除后还不行就根据代码分析吧!
5 context-path 配置
java
@Autowired
private RpcTransService rpcTransService;
//配置contextpath
rpcTransService.addContextPath("easyTrans","/api");
//或者
@Trans(type = TransType.RPC, targetClassName = "com.fhs.test.pojo.School", fields = {"schoolName"}, serviceName = "easyTrans", alias = "middle",serviceContextPath = "/api")
private String middleSchoolId;