## 前言
* 在以往的单工程项目,所有代码都融合在一起,业务相互调用只需要引入共有的工具类或者对应模块的service。
* 到了微服务时代,已然不能使用这种方式,我们需要寻找新的解决方案。
* 若每个模块都把需要调用模块的service拷贝一份,那会令代码非常冗余,影响整个工程的健壮性。
* 稍大一些的系统,会分成多个库,比如用户库、订单库分开,订单服务想要取到用户的相关信息,由于不能
* 连接到用户的库,所以无法直接新建数据库查询以达到目的。
* 这个时候,远程调用方案出现,订单服务只需调用用户服务的API,就可以获取所需信息,非常方便。
* 我们下面来看下如何使用SpringCloud的Feign来进行微服务远程调用。
## Feign简介
* Feign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign, 我们可以做到使用HTTP请求远程服
* 务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。
## 代码示例
1. 我们以 jpower-system 服务为例,让我们的 jpower-user 可以调用到 jpower-system 的API
2. 在jpower-system下新建了system-api工程,在该工程中新建package:com.wlcb.jpower.feign
![](https://img.kancloud.cn/f6/78/f6784b158f7888f6ec36bebe86b005de_698x496.png)
3. 在 com.wlcb.jpower.feign 下创建一个接口类,命名为 SystemClient
4. 增加如下代码,**下面代码是目前工程中已经实现的API接口**
~~~
/**
* @author mr.gmac
*/
@FeignClient(value = AppConstant.JPOWER_SYSTEM, path = "/core/")
public interface SystemClient {
/**
* @author null
* @Description //TODO 查询部门所有下级部门id
* @date 0:42 2020/9/3 0003
* @param id
* @return com.wlcb.jpower.module.base.vo.ResponseData
*/
@GetMapping("/org/queryChildById")
ResponseData> queryChildOrgById(@RequestParam String id);
@GetMapping("/org/queryOrgById")
ResponseData queryOrgById(@RequestParam String orgId);
@GetMapping("/client/getClientByClientCode")
ResponseData getClientByClientCode(@RequestParam String clientCode);
@GetMapping("/function/getUrlsByRoleIds")
ResponseData> getUrlsByRoleIds(@RequestParam List roleIds);
@GetMapping("/tenant/getTenantByCode")
ResponseData getTenantByCode(@RequestParam String tenantCode);
@GetMapping("/function/getMenuListByRole")
ResponseData> getMenuListByRole(@RequestParam List roleIds);
@GetMapping("/dataScope/getAllRoleDataScope")
ResponseData> getAllRoleDataScope();
@GetMapping("/dataScope/getDataScopeByRole")
ResponseData> getDataScopeByRole(@RequestParam List roleIds);
}
~~~
5. 继续新建`system-api-biz`工程maven继承 `system-api`,用来实现feign定义的接口,在工程中新建package:com.wlcb.jpower.controller
![](https://img.kancloud.cn/bc/5f/bc5fa449b68106e8d2f3a9faf7945f60_894x390.png)
6. 新建`SystemClientController`类,需要继承`SystemClient`接口类
![](https://img.kancloud.cn/f3/82/f3825e02f2f04efb34084289623280cb_778x416.png)
7. 增加如下,因为Feign本质上是HTTP客户端,所以我们创建的 BlogClientImpl 其实就是 SpringMVC 的 Controller ,所以需要加上 @RestController 注解。
**以下代码是工程目前已经实现的代码**
~~~
@ApiIgnore
@RestController
@RequestMapping("/core")
@AllArgsConstructor
public class SystemClientController implements SystemClient {
private CoreOrgService coreOrgService;
private CoreClientService coreClientService;
private CoreFunctionService coreFunctionService;
private TenantService tenantService;
private CoreDataScopeService coreDataScopeService;
@Override
@GetMapping("/org/queryChildById")
public ResponseData> queryChildOrgById(@RequestParam String id){
return ReturnJsonUtil.ok("查询成功",coreOrgService.queryChildById(id));
}
@Override
@GetMapping("/function/getUrlsByRoleIds")
public ResponseData> getUrlsByRoleIds(@RequestParam List roleIds) {
return ReturnJsonUtil.ok("查询成功",coreFunctionService.getUrlsByRoleIds(roleIds));
}
@Override
@GetMapping("/function/getMenuListByRole")
public ResponseData> getMenuListByRole(@RequestParam List roleIds) {
return ReturnJsonUtil.ok("查询成功",coreFunctionService.getMenuListByRole(roleIds));
}
@Override
@GetMapping("/dataScope/getAllRoleDataScope")
public ResponseData> getAllRoleDataScope() {
return ReturnJsonUtil.ok("查询成功",coreDataScopeService.getAllRoleDataScope());
}
@Override
@GetMapping("/dataScope/getDataScopeByRole")
public ResponseData> getDataScopeByRole(@RequestParam List roleIds) {
return ReturnJsonUtil.ok("查询成功",coreDataScopeService.getDataScopeByRole(roleIds));
}
@Override
@GetMapping("/tenant/getTenantByCode")
public ResponseData getTenantByCode(@RequestParam String tenantCode){
return ReturnJsonUtil.ok("查询成功",tenantService.getOne(Condition.getQueryWrapper().lambda().eq(TbCoreTenant::getTenantCode,tenantCode)));
}
@Override
@GetMapping("/org/queryOrgById")
public ResponseData queryOrgById(@RequestParam String orgId) {
return ReturnJsonUtil.ok("查询成功",coreOrgService.getById(orgId));
}
@Override
@GetMapping("/client/getClientByClientCode")
public ResponseData getClientByClientCode(@RequestParam String clientCode) {
return ReturnJsonUtil.ok("查询成功",coreClientService.loadClientByClientCode(clientCode));
}
}
~~~
8. 在`jpower-user`下的`user-biz`工程的 pom.xml 文件引入`jpower-system`的API包
![](https://img.kancloud.cn/a9/20/a9207b5bdca96f42f0693448737cd04d_1412x1532.png)
9. 找到`UserController`,新增如下代码
~~~
private SystemClient systemClient;
@GetMapping(value = "/orgDeatil",produces="application/json")
public ResponseData orgDeatil(String id){
ResponseData r = systemClient.queryOrgById(id);
return r;
}
~~~
10. 启动工程,我们去调用查看API调用返回结果
![](https://img.kancloud.cn/8d/4f/8d4f4cb1af05244830ef2e43130edadb_2912x1476.png)
11. 我们可以看到我们请求jpower-user服务的接口成功通过feign调用jpower-system查出了数据。
## 后续
* Feign调用我们已经走通,但是真实环境问题会很多,经常会有服务调用失败的情况。
* 应对这种场景,我们有没有什么好的解决方案?
* 下面我们来看下 Hystrix 熔断机制