一. 综述
之前微服务之间的调用是使用RestTemplate,虽然存在Eureka注册中心的情况下,可以使用服务提供者的name代替url。
但是类似“/SPRINGCLOUD-EMPLOYEE-PROVIDER/emp/list"
这种地址, 存在的问题是:
- 消费者必须要明确提供者的 application.name
- 还是太长,写起来还是很麻烦
- 等
Feign: 是Netflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API,”面向接口的形式“调用HTTP请求,达到就像调用本地方法一样调用远程HTTP请求的效果
Spring Cloud Feign:对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便,并赋予了负载均衡等强大的功能支持
Spring Cloud Feign的使用方法也很简单,主要有以下两种方式:
二. Feign使用步骤
使用的版本:spring-cloud-openfeign 2.1.0.RELEASE
SpringCloud版本:Greenwich.RELEASE
方式:服务提供者的RequestMapping和Feign接口的RequestMapping保持一致的形式
-
新建一个Maven模块,该模块只存放定义的Feign接口(因为消费者和提供者都需要使用该接口,所以将它们抽取出来单独部署成一个模块),添加依赖feign依赖
<dependencies> <!-- feign依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <!-- 这里会自动引入版本,类似parent标签继承 --> </dependency> </dependencies> <dependencyManagement> <dependencies> <!-- <scope>import</scope>解决单继承问题,类似parent标签, --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
-
在该模块下编写相应的服务接口
package feign.webservice; import com.fei.common.constant.ServerContant; import com.fei.common.model.employee.EmployeeModel; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import java.util.List; /** * @Author: xiaoshijiu * @Date: 2019/7/4 * @Description: 员工feign接口 * @FeignClient: name表示为哪个服务配置feign申明式服务调用 */ @FeignClient(name = ServerContant.SERVER_PROVIDER) @RequestMapping("/feign/empl") public interface EmployeeWebService { /** * 查询所有员工 * @return 员工模型列表 */ @RequestMapping(value = "/list", method = RequestMethod.GET) List<EmployeeModel> list(); }
在接口上添加注解
@FeignClient(name = ServerContant.SERVER_PROVIDER)
,表明这是一个Feign客户端,name属性表示具体为哪个服务配置
然后接口的具体方法可以填写@RequestMapping
,请求路径映射 -
服务提供者,需要编写和Feign定义的接口中方法的@RequestMapping一致的Controller方法,即服务提供者Controller中方法的@RequestMapping路径映射要和Feign接口中方法的路径映射一样。
package com.fei.springcloudprovide8001.webservice.feign; import com.alibaba.fastjson.JSON; import com.fei.common.model.employee.EmployeeModel; import com.fei.springcloudprovide8001.employee.EmployeeService; import feign.webservice.EmployeeWebService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * @Author: xiaoshijiu * @Date: 2019/7/4 * @Description: 服务提供者员工feign接口对应类 */ @RestController @RequestMapping("/feign/empl") public class EmployeeWebServiceImpl{ @Autowired private EmployeeService employeeService; /** * 查询所有员工 * @return 员工模型列表 */ @RequestMapping(value = "/list", method = RequestMethod.GET) public List<EmployeeModel> list() { // 使用阿里巴巴的fastjson进行集合中对象的模型转换 return JSON.parseArray(JSON.toJSONString(employeeService.list()), EmployeeModel.class); } }
-
服务消费者,就像调用本地方法一样去调用定义的feign接口就可以了
package com.fei.springcloudconsumer.consumer.employee.feign; import com.fei.common.model.employee.EmployeeModel; import feign.webservice.EmployeeWebService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; /** * @Author: xiaoshijiu * @Date: 2019/7/4 * @Description: feign组件,消费服务接口 */ @RestController @RequestMapping("/consume/feign/empl") public class EmployeeFeignController { /** * 使用了Feign,就像调用本地方法一样,调用远程HTTP请求 */ @Autowired private EmployeeWebService employeeWebService; /** * 获取员工列表,使用feign组件 */ @GetMapping("/list") public List<EmployeeModel> list2() { List<EmployeeModel> employeeModels = employeeWebService.list(); return webEmployeeModels; } }
有一点需要注意的是:这里的RequestMapping路径不能和Feign接口定义RequestMapping路径重复
-
最后要在服务消费者的主启动类上加上
@EnableFeignClients(basePackages = "feign.webservice")
注解,需要注意的是,如果你定义的Feign接口不在主启动类包或其子包下(即不在@ComponentScan
扫描范围内),则需添加basePackages
属性去指明Feign接口的包位置。
这一点很重要,不然会报不能@Autowired EmployeeWebService
的错。 -
测试,成功调用,并自带了Ribbon负载均衡的作用
-
下一篇:Feign使用的另一种方式:服务提供者实现Feign接口的形式