SPRING CLOUD微服务实战笔记--声明式服务调用:Spring Cloud Feign
Spring Cloud Feign
- 快速入门
- 参数绑定
- 继承特性
- Ribbon配置
- 全局配置
- 指定服务配置
- Hystrix配置
- 全局配置
- 禁用Hystrix
- 其他配置
- 请求压缩
- 日志配置
快速入门
通过Spring Cloud Feign提供的声明式服务绑定功能来实现对该服务接口的调用
创建Spring Boot工程,在pom.xml中引入依赖
org.springframework.cloud
spring-cloud-starter-feign
1.4.6.RELEASE 创建应用主类,并通过@EnableFeignClients注解开启Spring Cloud Feign的支持功能
@EnableFeignClients
@EnableEurekaClient
@SpringBootApplication
public class HelloApplication {public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}
定义HelloService接口,通过@FeignClient注解指定服务名来绑定服务,然后再使用SpringMVC的注解绑定具体该服务提供的REST接口
@FeignClient(“hello-service”)
public interface HelloService {@RequestMapping("/hello")
String hello();
}
创建一个ConsumerController来实现Feign客户端的调用
@RestController
public class ConsumerController {@Autowired
HelloService helloService;
@RequestMapping(value = "/feign-consumer" , method = RequestMethod.GET)
public String helloConsumer(){
return helloService.hello();
}
}
在application.properties中指定服务注册中心
spring.application.name=feign-consumer
server.port=9003
eureka.client.service-url.defaultZone=http://localhost:1111/eureka/
测试验证
访问http://localhost:9003/feign-consumer
,页面如下:
参数绑定
第一步:改造服务提供方的服务
服务提供方修改服务,增加接口定义,分别带有Request参数的请求,带有Header信息的请求,带有RequestBody的请求
@RequestMapping(value = "/hello1",method = RequestMethod.GET)
public String hello(@RequestParam String name){
return "Hello " + name;
}
@RequestMapping(value = "/hello2",method = RequestMethod.GET)
public User hello(@RequestHeader String name,@RequestHeader Integer age){
return new User(name,age);
}
@RequestMapping(value = "/hello3" , method = RequestMethod.POST)
public String hello(@RequestBody User user){
return "Hello " + user.getName() + ", " + user.getAge();
}
User对象定义如下:
public class User {
private String name;
private Integer age;
public User(){ }
public User(String name,Integer age){
this.name = name;
this.age = age;
}
//省略getter和setter方法
@Override
public String toString(){
return "name=" + name + ",age=" + age;
}
}
第二步:改造服务消费端的请求绑定
- 在feign-consumer中添加和上面一样的User类
在HelloService中增加三个新增接口的绑定声明
@FeignClient(“hello-service”)
public interface HelloService {@RequestMapping("/hello")
String hello();
@RequestMapping(value="/hello1",method = RequestMethod.GET)
String hello(@RequestParam("name") String name);
@RequestMapping(value = "/hello2",method = RequestMethod.GET)
User hello(@RequestHeader("name") String name,@RequestHeader("age") Integer age);
@RequestMapping(value = "/hello3",method = RequestMethod.POST)
String hello(@RequestBody User user);
}
在ConsumerController中新增一个/feign-consumer2接口,对新增接口进行调用
@RequestMapping(value = “/feign-consumer2”,method = RequestMethod.GET)
public String helloConsumer2(){
StringBuilder sb = new StringBuilder();
sb.append(helloService.hello()).append("\n");
sb.append(helloService.hello("DIDI")).append("\n");
sb.append(helloService.hello("DIDI",30)).append("\n");
sb.append(helloService.hello(new User("DIDI",30))).append("\n");
return sb.toString();
}
测试验证
访问http://localhost:9003/feign-consumer2
,返回如下:
Hello World! Hello DIDI name=DIDI,age=30 Hello DIDI, 30
继承特性
通过Spring Cloud Feign的继承特性来实现REST接口定义的复用
先新建一个Maven工程:
- 创建一个Maven工程,命名为hello-service-api
修改工程的pom,引入依赖
4.0.0 <groupId>com.didispace</groupId>
<artifactId>hello-service-api</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>hello-service-api</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.7.RELEASE</version>
<relativePath></relativePath>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
将上一节实现的User对象复制到hello-service-api工程中
在Maven工程中添加HelloService
@RequestMapping(“/refactor”)
public interface HelloService {@RequestMapping(value = "/hello4",method = RequestMethod.GET)
public String hello(@RequestParam String name);
@RequestMapping(value = "/hello5",method = RequestMethod.GET)
public User hello(@RequestHeader String name, @RequestHeader Integer age);
@RequestMapping(value = "/hello6" , method = RequestMethod.POST)
public String hello(@RequestBody User user);
}
再修改服务提供方,对其进行重构
修改pom.xml,新增对hello-service-api的依赖
com.didispace
hello-service-api
0.0.1-SNAPSHOT 创建RefactorHelloController类继承hello-service-api中定义HelloService接口,并实现这个接口中的方法
@RestController
public class RefactorHelloController implements HelloService {@Override
public String hello(@RequestParam("name") String name) {
return "Hello " + name;
}
@Override
public User hello(@RequestHeader("name") String name,@RequestHeader("age") Integer age) {
return new User(name,age);
}
@Override
public String hello(@RequestBody User user) {
return "Hello " + user.getName() + ", " + user.getAge();
}
}
最后修改服务消费者
修改pom.xml,新增对hello-service-api的依赖
com.didispace
hello-service-api
0.0.1-SNAPSHOT 创建RefactorHelloService接口,并继承hello-service-api包中的HelloService接口,然后添加@FeignClient注解来绑定服务
@FeignClient(value = “HELLO-SERVICE”)
public interface RefactorHelloService extends com.didispace.service.HelloService{
}在ConsumerController中,注入RefactorHelloService的实例,并新增一个请求/feign-consumer3来触发RefactorHelloService的实例
@RequestMapping(value = “/feign-consumer3”,method = RequestMethod.GET)
public String helloConsumer3(){
StringBuilder sb = new StringBuilder();
sb.append(refactorHelloService.hello("MIMI")).append("\n");
sb.append(refactorHelloService.hello("MIMI",30)).append("\n");
sb.append(refactorHelloService.hello(new com.didispace.User.User("MIMI",20))).append("\n");
return sb.toString();
}
遇到的问题:
将项目引入到maven私服库的时候,项目中调用接口不能识别,原来之前为了打包将pom中的编译插件换了,导致执行mvn install
命令时编译有问题
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.0.3.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
将上面这段从pom中删除,重新执行mvn install
后成功
Ribbon配置
全局配置
通过使用ribbon.=方式来设置ribbon的各项默认参数,比如修改默认的客户端调用超时时间:
ribbon.ConnectTimeout = 500
ribbon.ReadTimeout=5000
指定服务配置
有时需要个性化配置,采用.ribbon.key=value的格式进行设置
使用@FeignClient(value = “HELLO-SERVICE”)来创建Feign客户端的时候,同时也创建了一个名为HELLO-SERVICE的Ribbon客户端
HELLO-SERVICE.ribbon.ConnectTimeout=500
HELLO-SERVICE.ribbon.ReadTimeout=2000
Hystrix配置
全局配置
Hystrix的全局配置采用默认配置前缀hystrix.command.default
就可以设置,比如设置全局的超时时间:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
通过feign.hystrix.enabled=false
来全局关闭Hystrix功能
通过feign.command.default.execution.timeout.enabled=false
来关闭熔断功能
禁用Hystrix
@Scope(“prototype”)注解为指定的客户端配置Feign.Builder实例
构建一个Hystrix配置类
@Configuration
public class DisableHystrixConfiguration{@Bean
@Scope("prototype")
public Feign.Builder feignBuilder(){
return Feign.builder();
}
}
在HelloService的@FeignClient注解中,通过configuration参数引入上面实现的配置
@FeignClient(name=”HELLO-SERVICE”,configuration =DisableHystrixConfiguration.class)
public interface HelloService{
}
其他配置
请求压缩
SpringCloudFeign支持对请求与响应进行GZIP压缩,以减少通信过程中的性能损耗
feign.compression.request.enabled=true
feign.compression.response.enabled=true
同时还可以进行更加细化的配置
feign.compression.request.enabled=true;
//指定压缩请求数据类型
feign.comresstion.request.mime-types=text/xml,application/xml,application/json
//请求压缩的大小下限,只有查过这个大小的请求才会对其进行压缩
feign.compression.request.min-request-size=2048
日志配置
可以在application.properties文件中使用logging.level.<FeignClient>
的参数配置格式来开启指定Feign客户端的DEBUG日志,其中<FeignClient>
为Feign客户端定义接口的完整路径,比如:
logging.level.com.didispace.web.HelloService=DEBUG
同时调整全局的日志级别,可以在应用主类中直接加入Logger.Level的Bean创建,具体如下:
@EnableFeignClients
@EnableEurekaClient
@SpringBootApplication
public class HelloApplication {
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}
对于Feign的Logger级别主要有如下4类,可以根据实际需要进行调整使用
- NONE:不记录任何信息
- BASIC:仅记录请求方法,URL以及响应状态码和执行时间
- HEADERS:除了记录BASIC级别的信息之外,还会记录请求和响应的头信息
- FULL:记录所有请求与响应的明细,包括头信息,请求体和元数据等
还没有评论,来说两句吧...