目录
1 Feign解决的问题
使用RestTemplate调用其他服务的API时,请求参数需要在URL后面拼接,参数少的情况下没有影响,参数多的轻轻下去拼接String效率非常低,操作起来也非常不灵活容易出错,Feign就应运而生解决了这个问题。
Feign是一个声明式的Web Service客户端,是为了让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。
Feign会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Feign整合了Ribbon和Hystrix(关于Hystrix我们后面再讲),可以让我们不再需要显式地使用这两个组件。
2 创建Feign实例
创建项目springcloud-feign,引入Feign依赖,会自动引入Hystrix依赖的,pom.xml文件配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud-feign-demo</artifactId>
<groupId>com.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.springcloud</groupId>
<artifactId>springcloud-feign</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
application.yml配置如下:
server:
port: 9006
spring:
application:
name: feign-consumer
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/
在提供者spirngcloud-provider1的ProviderController.java修改为:
@RestController
public class ProviderController {
@RequestMapping("/hello")
public String hello(){
System.out.println("访问来1了......");
return "hello1";
}
//新增的方法
@RequestMapping(value = "/hellol", method= RequestMethod.GET)
public String hello(@RequestParam String name) {
return "HelloProvider1 " + 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 "HelloProvider1 "+ user. getName () + ", " + user. getAge ();
}
}
把服务提供者spirngcloud-provider2的ProviderController.java修改为:
@RestController
public class ProviderController {
@RequestMapping("/hello")
public String hello(){
System.out.println("访问来1了......");
return "HelloProvider2";
}
//新增的方法
@RequestMapping(value = "/hellol", method= RequestMethod.GET)
public String hello(@RequestParam String name) {
return "HelloProvider2 " + 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 "HelloProvider2 "+ user. getName () + ", " + user. getAge ();
}
}
在服务提供者springcloud-provider1,springcloud-provider2以及服务消费者springcoud-fegin中分别添加实体类User.java
@Data
public class User {
private String name;
private Integer age;
public User(){
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
}
使用Feign的@FeignClient映射服务调用:
@FeignClient(value = "hello-service",fallback = FeignFallBack.class)
public interface FeignService {
//服务中方法的映射路径
@RequestMapping("/hello")
String hello();
@RequestMapping(value = "/hellol", 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);
}
处理服务降级:
@Component
public class FeignFallBack implements FeignService {
//实现的方法是服务调用的降级方法
@Override
public String hello() {
return "error";
}
@Override
public String hello(String name) {
return "error";
}
@Override
public User hello(String name, Integer age) {
return new User();
}
@Override
public String hello(User user) {
return "error";
}
}
controller层注入接口FeignService进行远程调用:
@RestController
public class ConsumerController {
@Autowired
FeignService feignService;
@RequestMapping("/consumer")
public String helloConsumer(){
return feignService.hello();
}
@RequestMapping("/consumer2")
public String helloConsumer2(){
String result1 = feignService.hello("boy");
String result2 = feignService.hello("boy", 30).toString();
String result3 = feignService.hello(new User("boy", 30));
return result1 + "-----" + result2 + "----" + result3;
}
}
创建启动类FeignApplication.java,打上eureka客户端的注解@EnableDiscoveryClient,以及Feign客户端的注解@EnableFeignClients
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApplication.class, args);
}
}
启动服务注册中心springcloud-eureka1,springcloud-eureka2;启动服务提供者springcloud-provider1,springcloud-provider2;启动服务消费者springcloud-feign。浏览器访问:
http://localhost:9006/consumer
轮询得到如下结果:
可以看到轮询得到HelloProvider1和HelloProvider1两个结果,浏览器访问:
http://localhost:9006/consumer2
轮询得到如下结果
停掉服务springcloud-provider1,springcloud-provider2,浏览器访问
可以看到调用都进行了服务降级。
3 总结
本文介绍了Feign的使用方法,Feign使用@FeignClient映射服务,大大提升了服务请求的便捷性,在实际的工作中大多数会使用这种方式。本文的源码下载地址:https://github.com/xiaoyususu/springcloud-feign-demo.git