【摘要】 服务注册中心Feign可以配合eureka等服务注册中心同时使用。eureka来作为服务注册中心,为Feign提供关于服务端信息的获取,比如说IP地址。关于eureka的具体使用可以参考关于eureka的快速入门介绍。 服务提供者Spring Cloud Feign是声明式RESTful请求客户端,所以它不会侵入服务提供者程序的实现。也就是说,服务提供者只需要提供Web Service的A…
服务注册中心
Feign
可以配合eureka
等服务注册中心同时使用。eureka
来作为服务注册中心,为Feign
提供关于服务端信息的获取,比如说IP地址。关于eureka
的具体使用可以参考关于eureka
的快速入门介绍。
服务提供者
Spring Cloud Feign
是声明式RESTful请求客户端,所以它不会侵入服务提供者程序的实现。也就是说,服务提供者只需要提供Web Service的API接口,至于具体实现既可以是Spring Controler
也可以是Jersey
。我们只需要确保该服务提供者被注册到服务注册中心上。
@RestController
@RequestMapping("/feign-service")
public class FeignServiceController {
private static final Logger logger = LoggerFactory.getLogger(FeignServiceController.class);
private static String DEFAULT_SERVICE_ID = "application";
private static String DEFAULT_HOST = "localhost";
private static int DEFAULT_PORT = 8080;
@RequestMapping(value = "/instance/{serviceId}", method = RequestMethod.GET)
public Instance getInstanceByServiceId(@PathVariable("serviceId") String serviceId){
logger.info("Get Instance by serviceId {}", serviceId);
return new Instance(serviceId, DEFAULT_HOST, DEFAULT_PORT);
}
@RequestMapping(value = "/instance/{serviceId}", method = RequestMethod.DELETE)
public String deleteInstanceByServiceId(@PathVariable("serviceId") String serviceId){
logger.info("Delete Instance by serviceId {}", serviceId);
return "Instance whose serviceId is " + serviceId + " is deleted";
}
@RequestMapping(value = "/instance", method = RequestMethod.POST)
public String createInstance(@RequestBody Instance instance){
logger.info("Create Instance whose serviceId is {}", instance.getServiceId());
return "Instance whose serviceId is" + instance.getServiceId() + " is created";
}
@RequestMapping(value = "/instance/{serviceId}", method = RequestMethod.PUT)
public String updateInstanceByServiceId(@RequestBody Instance instance, @PathVariable("serviceId") String serviceId){
logger.info("Update Instance whose serviceId is {}", serviceId);
return "Instance whose serviceId is " + serviceId + " is updated";
}
}
上述代码中通过@RestController
和@RequestMapping
声明了四个网络API接口,分别是对Instance
资源的增删改查操作。
除了实现网络API接口之外,还需要将该service注册到eureka
上。如下列代码所示,需要在application.yml
文件中设置服务注册中心的相关信息和代表该应用的名称。
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-service
server:
port: 0
服务消费者
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
的相关使用原理有了一定的了解,相信这个过程将对于理解Feign
相关的工作原理大有裨益。