SpringCloud Feign 声明式服务调用
服务调用有2种方式:REST、RPC,SpringCloud一般用RestTemplate来实现REST调用,
此外SpringCloud还可以使用Feign来调用服务,Feign是声明式的服务调用,所谓声明式就是通过服务接口来调用,和RPC相似。
REST使用HTTP协议,RPC使用TCP协议,Feign只是伪RPC调用,因为Feign底层使用的协议是HTTP。
Eureka、Ribbon、Feign都是Netflix旗下的项目,都被SpringCloud集成了。
此处写一个feign的demo,获取用户的所有订单,user-service调用order-service
服务消费者user-service
(1)创建时勾选Spring Cloud Routing -> OpenFeign,当然Eureka Client、Spring Web等等也要勾选,不用勾选Ribbon,Eureka Client中已经包含了Ribbon的依赖
也可以收手动加feign的依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
(2)引导类上加 @EnableFeignClients
(3)新建包feign用来存放feign服务调用的接口,包下新建接口OrderFeignService
@FeignClient("order-service") //参数指定要调用的服务名称。feign也内置了ribbon,会自动实现负载均衡 public interface OrderFeignService { @GetMapping("/api/v1/order/list") //该服务要调用的地址,不需要使用RESTful风格 List<Order> findOrdersByUserId(@RequestHeader("user_id") Integer user_id); //使用参数表传递参数 }
一个要调用的服务对应一个接口,如果要调用多个服务,写多个接口。
使用参数表传递参数,每个参数前都要加注解。
启动应用时检测到引导类上有@EnableFeignClients,会扫描@FeignClient标注的接口,给该接口生成动态代理(使用RestTemplate来代理),放在Spring容器中。
调用服务时,底层还是使用RestTemplate来调用服务,使用的还是HTTP协议。
(4)controller
@Controller @RequestMapping("/api/v1/user") public class UserController { //注入要调用的服务接口,实际是注入动态代理生成的RestTemplate
@Resource private OrderFeignService orderFeignService; //根据用户id查找用户所有订单 @GetMapping("/order/{user_id}") @ResponseBody public List<Order> findOrdersByUserId(@PathVariable Integer user_id){ //调用Feign客户端(接口)的方法,传入需要的参数 List<Order> orderList = orderFeignService.findOrdersByUserId(user_id); return orderList; } }
实际写代码时要在service层调用服务。
Feign比RestTemplate要麻烦些,底层还是调用RestTemplate,还要包装为代理对象,时间、资源开销都增加了;
一会儿用RESTful风格传参,一会@RequestHeader传参,不统一,如果要在被调者中使用RESTful风格,还需要再写一个方法映射为RESTful风格。
但把服务调用写成接口,使得服务调用也是面向接口编程的,消费者、提供者没有耦合在业务方法(类)中,使用接口对接降低了耦合;
升级时只需修改feign包下的feign接口,不必到处修改RestTemplate的调用,好维护,所以feign也很常用。
服务提供者
@Controller @RequestMapping("/api/v1/order") public class OrderController { //根据用户id查找该用户的所有订单 @GetMapping("/list") //请求方式、映射地址都要和消费者中的Feign接口对应 @ResponseBody public List<Order> findAllByUserId(@RequestHeader("user_id") Integer user_id){ //参数表要和消费者中Feign接口中方法的参数表对应 //一些列操作 //...... return orderList; } }
Feign有一个很不好地方的:传参方式不统一,消费者用@RequestHeader传参,提供者也要用这个来接收,难以统一使用RESTful
消费者使用@RequestHeader传,提供者只能使用@RequestHeader、@RequestParam来接收。
消费者使用@RequestBody传,提供者只能使用@RequestBody、@RequestParam来接收。
@RequestParam是通用的,请求头、请求体中的数据都可以接收。
一般地,少量数据比如int、String使用@RequestHeader传输,大量数据比如Map、User对象使用@RequestBody来传输。
使用@RequestBody时,映射方式要使用@PostMapping,不能使用@GetMapping,因为体积大,要使用post。
@RequestHeader是将数据绑定到请求头,使用Get方式传输,或者从请求头中获取数据;
@RequestBody是将数据绑定大请求体,使用Post方式传输,或者从请求体中获取数据。
@PathVariable是接收Restful风格的url中的参数。
Restful有个缺点:能传递的数据类型有限,毕竟要写在url中,不能是User之类的对象。
映射方式:
@RequestMapping可以接收、处理所有请求方式中的某一种,需使用method属性指定,不指定时默认为 RequestMethod.GET
@GetMapping只接收、处理GET方式的请求,是@RequestMapping(method=RequestMethod.GET)的简写
@PostMapping只接收、处理POST方式的请求,是@RequestMapping(method=RequestMethod.POST)的简写
@PutMapping
@DeleteMapping
相关文章
- Springcloud 配置 | 史上最全,一文全懂
- SpringCloud-高可用的分布式配置中心(config)
- SpringCloud微服务(03):Hystrix组件,实现服务熔断
- SpringCloud微服务(02):Ribbon和Feign组件,实现服务调用的负载均衡
- 《springCloud系列》——Eureka 进行服务治理
- 小团队真的适合引入SpringCloud微服务吗?
- 微服务技术系列教程(42)- SpringCloud -Sleuth与Zipkin服务链路
- 微服务技术系列教程(41)- SpringCloud -OAuth2搭建微服务开放平台
- 微服务技术系列教程(22) - SpringCloud- 服务保护机制Hystrix
- 微服务技术系列教程(18) - SpringCloud- 服务治理Eureka(集群搭建)
- SpringCloud Config(配置中心)实现配置自动刷新(十六)
- SpringCloud之异常报警通知(八)
- Linux Nacos 集群安装,springCloud Nacos Linux 安装和集群配置
- SpringCloud Eureka安装和使用,SpringCloud使用Eureka作为服务注册中心
- 使用springcloud的feign调用服务时出现的错误:关于实体转换成json错误的介绍
- springcloud 微服务架构之eureka服务注册与发现
- 【毕业设计_课程设计】基于SpringCloud的微服务人才招聘系统设计与实现
- 玩转springcloud:IDEA如何创建一个父工程和多个module,都给你总结好了
- 玩转springcloud:springcloud组件的停更你值得拥有阿里巴巴的springcloud
- SpringCloud之Eureka:服务发布与调用例子
- Jenkins+Docker+Harbor+SpringCloud微服务持续集成(下)
- SpringCloud 无法调用内部服务的问题:EnableFeignClients的basePackages
- 通过SpringBoot、SpringCloud搭建微服务框架,集成Redis、RabbitMQ实现限流、解耦、异步、服务拆分,Eureka做服务注册,Zuul网关,前后端分离,RESTful接口风格