
正文
Spring Cloud(Dalston.SR5)--Feign 声明式REST客户端
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
Spring Cloud 对 Feign 进行了封装,集成了 Ribbon 并结合 Eureka 可以实现客户端的负载均衡,Spring Cloud 实现的 Feign 客户端类名为 LoadBalancerFeignClient,在该类中,维护着与 SpringClientFactory 相关的实例,通过SpringClientFactory 可以获取负载均衡器,负载均衡器会根据一定的规则来选取处理请求的服务器,最终实现负载均衡功能。
集成了 Hystrix 增加了服务容错处理,并为 Feign 的使用提供了各种默认属性,例如编码器、解码器、日志、注解翻译器、实例创建者和客户端,我们可以简单的使用 Feign,也可以增加自定义的配置,下面我们在 Spring Cloud 中使用 Feign 示例如下:
-
创建项目
创建名称为 spring-cloud-feign-client 的 Spring Cloud 项目,修改 POM.xml 中增加以下依赖项:
<? xmlversion="1.0"encoding="UTF-8" ?>
< projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion >4.0.0</ modelVersion >
< groupId >org.lixue</ groupId >
< artifactId >spring-cloud-feign-client</ artifactId >
< version >0.0.1-SNAPSHOT</ version >
< packaging >jar</ packaging >
< name >spring-cloud-feign-client</ name >
< description >DemoprojectforSpringBoot</ description >
< parent >
< groupId >org.springframework.boot</ groupId >
< artifactId >spring-boot-starter-parent</ artifactId >
< version >1.5.4.RELEASE</ version >
< relativePath /> <!--lookupparentfromrepository-->
</ parent >
< properties >
< project.build.sourceEncoding >UTF-8</ project.build.sourceEncoding >
< project.reporting.outputEncoding >UTF-8</ project.reporting.outputEncoding >
< java.version >1.8</ java.version >
< spring-cloud.version >Dalston.SR5</ spring-cloud.version >
</ properties >
< 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 >
< dependency >
< groupId >org.springframework.boot</ groupId >
< artifactId >spring-boot-starter-test</ artifactId >
< scope >test</ scope >
</ dependency >
</ dependencies >
< dependencyManagement >
< dependencies >
< dependency >
< groupId >org.springframework.cloud</ groupId >
< artifactId >spring-cloud-dependencies</ artifactId >
< version >${spring-cloud.version}</ version >
< type >pom</ type >
< scope >import</ scope >
</ dependency >
</ dependencies >
</ dependencyManagement >
< build >
< plugins >
< plugin >
< groupId >org.springframework.boot</ groupId >
< artifactId >spring-boot-maven-plugin</ artifactId >
</ plugin >
</ plugins >
</ build >
</ project >
-
创建 Feign 接口
在 Spring Cloud 中使用 Feign ,需要使用的是 Spring Cloud 的相关注解,例如 @RequestMapping、@RequestParam 等,而不是 Feign 的注解,创建 HelloWorldClient 接口,使用 @FeignClient 注解来标注服务名称(调用服务的 spring.application.name 属性),使用 @RequestMapping 来标注 REST 服务的相关属性;@RequestParam 和 @PathVariable 注解标注请求参数
package org.lixue;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient( "helloworld-provider" )
public interface HelloWorldClient{
@RequestMapping(path= "/speak?body={body}" ,method=RequestMethod. GET )
String speak(@RequestParam(value= "body" ,required= false ) String body);
@RequestMapping(path= "/person/{personId}" ,method=RequestMethod. GET ,
produces=MediaType. APPLICATION_JSON_UTF8_VALUE )
Person findById(@PathVariable( "personId" )Integer personId);
@RequestMapping(path= "/person/create" ,method=RequestMethod. POST ,
consumes=MediaType. APPLICATION_JSON_UTF8_VALUE ,
produces=MediaType. APPLICATION_JSON_UTF8_VALUE )
ReturnValue create(Person person);
}
-
启动类启用 Feign
Feign 集成了 Ribbon 并结合 Eureka 可以实现客户端的负载均衡,因此在启动类我们需要启动 Eureka客户端和 Feign,使用 @EnableEurekaClient 启用 Eureka 客户端;使用 @EnableFeignClients 启用 Feign
package org.lixue;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class SpringCloudFeignClientApplication{
public static void main(String[]args){
SpringApplication. run (SpringCloudFeignClientApplication. class ,args);
}
}
-
增加配置
Feign 集成了 Ribbon 并结合 Eureka 可以实现客户端的负载均衡,因此需要增加 Eureka 相关配置,指定 eureka 服务注册中心的地址
##配置应用名称
spring:
application:
name: spring-cloud-feign-client
#配置服务端口
server:
#设置eureka服务注册中心的地址,如果多个以逗号分割
eureka:
client:
service-url:
defaultZone: http://eurekaserver01:9000/eureka/,http://eurekaserver02:9000/eureka/
-
创建 REST 服务
在调用服务时,只需要使用 @Autowired 注解标注 Feign 接口 HelloWorldClient , Spring Cloud 会帮我们创建和维护客户端实例
package org.lixue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
@RestController
public class InvokerController{
@Autowired
private HelloWorldClient helloWorldClient ;
@RequestMapping(path= "/invokerSpeak" ,method=RequestMethod. GET )
public String invokerSpeak(@RequestParam(name= "body" ,required= false )String body){
return helloWorldClient .speak(body);
}
@RequestMapping(path= "/invokerFindByID/{personID}" ,method=RequestMethod. GET ,
produces=MediaType. APPLICATION_JSON_UTF8_VALUE )
public Person invokerFindByID(@PathVariable( "personID" )Integer personID){
return helloWorldClient .findById(personID);
}
@RequestMapping(path= "/invokerCreate" ,method=RequestMethod. GET ,
produces=MediaType. APPLICATION_JSON_UTF8_VALUE )
ReturnValue invokerCreate(){
Person newPerson= new Person();
newPerson.setId(3434);
newPerson.setAge(34);
newPerson.setName( "343434" );
newPerson.setMessage( "33333333333333333" );
return helloWorldClient .create(newPerson);
}
}
-
测试验证
启动 eureka-server 和 service-provider 项目,启动该项目后,访问地址 http://localhost:8070/invokerSpeak 可以查看到访问,如果启动了多个 service-provider ,多次刷新可以看到,具体的服务调用被轮询调用。
日志配置
启用服务的 Feign 日志,增加配置 Bean 如下:
package org.lixue;
import feign.Logger;
import org.springframework.context.annotation.Bean;
public class MyFeignConfiguration{
@Bean
public Logger.Level level(){
return Logger.Level. FULL ;
}
}
在 Feign 接口的 @FeignClient 注解中,增加 configuration 指向到创建的配置类:
@FeignClient(value= "helloworld-provider" ,configuration=MyFeignConfiguration. class )
public interface HelloWorldClient{
//其他代码如上
}
修改 src/main/resources 目录下的 application.yml 增加日志级别配置:
logging:
level:
org.lixue.HelloWorldClient: debug
此时就可以看到请求日志的输出,如下:
2018-04-06 12:43:24.578 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] ---> GET http://helloworld-provider/speak HTTP/1.1
2018-04-06 12:43:24.581 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] ---> END HTTP (0-byte body)
2018-04-06 12:43:25.112 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] <--- HTTP/1.1 200 (529ms)
2018-04-06 12:43:25.112 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] content-length: 21
2018-04-06 12:43:25.113 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] content-type: text/plain;charset=UTF-8
2018-04-06 12:43:25.113 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] date: Fri, 06 Apr 2018 04:43:25 GMT
2018-04-06 12:43:25.113 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] x-application-context: helloworld-provider:8001
2018-04-06 12:43:25.113 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak]
2018-04-06 12:43:25.118 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] hello world port:8001
2018-04-06 12:43:25.118 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] <--- END HTTP (21-byte body)
默认配置
Spring Cloud 为 Feign 的使用提供了各种默认属性,默认情况下,Spring 将会为 Feign 的属性提供以下 Bean 来实现 Feign 的调用
|
Bean 类型 |
Bean 名称 |
实现类 |
说明 |
|
Decoder |
feignDecoder |
ResponseEntityDecoder |
解码器 |
|
Encoder |
feignEncoder |
SpringEncoder |
编码器 |
|
Logger |
feignLogger |
Slf4jLogger |
日志 |
|
Contract |
feignContract |
SpringMvcContract |
注解翻译器 |
|
Feign.Builder |
feignBuilder |
HystrixFeign.Builder |
Feign 实例创建者 |
|
Client |
feignClient |
|
Feign 客户端,启用 Ribbon 实现类为LoadBalancerFeignClient 否则为 Feign 默认实现类 |
|
Logger.Level |
自命名 |
无 |
没有默认提供,只需要提供该类型的 Bean 即可 |
|
Retryer |
自命名 |
无 |
没有默认提供,只需要提供该类型的 Bean 即可 |
|
ErrorDecoder |
自命名 |
无 |
没有默认提供,只需要提供该类型的 Bean 即可 |
|
Request.Options |
自命名 |
无 |
没有默认提供,只需要提供该类型的 Bean 即可 |
|
RequestInterceptor |
自命名 |
无 |
没有默认提供,只需要提供该类型的 Bean 即可 |







