feign 服务消费者实现
核心组件与概念
在阅读Feign
源码时,可以沿着两条路线进行,一是FeignServiceClient
这样的被@FeignClient
修饰的接口类如何被创建出来,也就是其Bean对象是如何被构建的,二是调用FeignServiceClient
对象的响应方法时,Feign
是如何发送网络请求的。而Feign
相关的类也可以以此来进行分类,一部分是用来初始化相应的Bean示例的,一部分是用来在调用方法时发送网络请求的。
上图是Feign
相关的关键类图,其中比较重要的类为FeignClientFactoryBean
,FeignContext
,SynchronousMethodHandler
。其中FeignClientFactoryBean
可以创建@FeignClient
修饰的接口类Bean示例;FeignContext
作为配置的上下文环境,保存着相关组件的不同实例,这些示例都是按照不同的FeignConfiguration
所构造出来的;SynchronousMethodHandler
是MethodHandler
的子类,可以在相应方法被调用时发送网络请求,然后再将请求响应转化为函数返回值进行输出。
图是后续源码讲解的流程图,Feign
会首先进行相关BeanDefinition的动态注册,然后当spring
容器注入相关实例时会进行实例的初始化,最后当相关实例的函数被调用时会进行发送网络请求。
服务消费者
Feign
是声明式RESTful客户端,所以构建Feign
项目的关键在于构建服务消费者。通过下面六步可以创建一个Spring Cloud Feign
的服务消费者。
第一步: 创建普通的Spring Boot工程
首先创建一个普通的Spring Boot
工程,取名为chapter-feign-client
。
第二步:添加依赖
需要在pom文件中添加eureka
和feign
相关的依赖。其中spring-cloud-starter-eureka
是eureka
的starter依赖包,spring-cloud-starter-feign
是feign
的starter依赖包。
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
</dependencies>
添加注解
然后在工程的入口类上添加@EnableFeignClients
注解表示开启Spring Cloud Feign
的支持功能,代码如下所示。
@SpringBootApplication
@EnableFeignClients()
public class ChapterFeignClientApplication {
public static void main(String[] args) {
SpringApplication.run(ChapterFeignClientApplication.class, args);
}
}
@EnableFeignClients
就像是一个开关,如果你使用了该注解,那么Feign
相关的组件和处理机制才会生效,否则不会生效。@EnableFeignClients
还可以对Feign
相关组件进行自定义配置,它的方法和原理会在本章的源码分析章节在做具体的讲解。
第四步:声明服务
接下来我们定义一个FeignServiceClient
接口,通过@FeignClient
注解来指定服务名进而绑定服务。这一类被@FeignClient
修饰的接口类一般被称为FeignClient。我们可以通过@RequestMapping
来修饰相应的方法来定义调用函数。
@FeignClient("feign-service")
@RequestMapping("/feign-service")
public interface FeignServiceClient {
@RequestMapping(value = "/instance/{serviceId}", method = RequestMethod.GET)
public Instance getInstanceByServiceId(@PathVariable("serviceId") String serviceId);
@RequestMapping(value = "/instance/{serviceId}", method = RequestMethod.DELETE)
public String deleteInstanceByServiceId(@PathVariable("serviceId") String serviceId);
@RequestMapping(value = "/instance", method = RequestMethod.POST)
public String createInstance(@RequestBody Instance instance);
@RequestMapping(value = "/instance/{serviceId}", method = RequestMethod.PUT)
public String updateInstanceByServiceId(@RequestBody Instance instance, @PathVariable("serviceId") String serviceId);
}
如上面代码片段所显示的,如果你调用FeignServiceClient
对象的getInstanceByServiceId
函数,那么Feign
就会向feign-service
服务的/feign-service/instance/{serviceId}
接口发送网络请求。
第五步:Controller中调用服务
创建一个Controller
来调用上边的服务,通过@Autowired
来自动装载FeignServiceClient
示例。代码如下:
@RestController
@RequestMapping("/feign-client")
public class FeignClientController {
@Autowired
FeignServiceClient feignServiceClient;
@RequestMapping(value = "/instance/{serviceId}", method = RequestMethod.GET)
public Instance getInstanceByServiceId(@PathVariable("serviceId") String serviceId){
return feignServiceClient.getInstanceByServiceId(serviceId);
}
@RequestMapping(value = "/instance/{serviceId}", method = RequestMethod.DELETE)
public String deleteInstanceByServiceId(@PathVariable("serviceId") String serviceId){
return feignServiceClient.deleteInstanceByServiceId(serviceId);
}
@RequestMapping(value = "/instance", method = RequestMethod.POST)
public String createInstance(@RequestBody Instance instance){
return feignServiceClient.createInstance(instance);
}
@RequestMapping(value = "/instance/{serviceId}", method = RequestMethod.PUT)
public String updateInstanceByServiceId(@RequestBody Instance instance, @PathVariable("serviceId") String serviceId){
return feignServiceClient.updateInstanceByServiceId(instance, serviceId);
}
}
第六步:属性配置
最后,application.yml
中需要配置eureka
服务注册中心的相关配置,具体配置如下所示:
eureka:
instance:
instance-id: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
client:
service-url:
default-zone: http://localhost:8761/eureka/
spring:
application:
name: feign-client
server:
port: 8770
相信你通过搭建Feign
的项目,已经对Feign
的相关使用原理有了一定的了解,相信这个过程将对于理解Feign
相关的工作原理大有裨益。
- 点赞
- 收藏
- 关注作者
评论(0)