前面使用了Ribbon做客户端负载均衡,使用Hystrix做容错保护,这两者被作为基础工具类框架被广泛地应用在各个微服务的实现中。SpringCloudFeign是将两者做了更高层次的封装以简化开发。它基于Netfix Feign实现,整合了SpringCloudRibbon和SpringCloudHystrix,除了提供这两者的强大功能外,还提供了一种声明是的Web服务客户端定义的方式。SpringCloudFeign在NetFixFeign的基础上扩展了对SpringMVC注解的支持,在其实现下,我们只需创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口绑定。简化了SpringCloudRibbon自行封装服务调用客户端的开发量。
快速使用
接着之前的代码:SpringCloud容错保护Hystrix(二)
代码地址:https://gitee.com/wqh3520
1.创建一个SpringBoot工程,这里命名为feign-consumer,然后在pom文件中添加依赖:
.....
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-feign
org.springframework.boot
spring-boot-starter-web
2.在主类上使用@EnableFeignClients注解开启SpringCloudFeign的支持功能
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApplication.class, args);
}
}
3.接口定义:我们这里调用USER-SERVICE服务,在该服务中创建一个查询所有用户的接口,然后在feign-consumer中定义。
USER-SERVICE
@RestController
public class UserFeignController {
@Autowired
private UserRepository userRepository;
@GetMapping("/feign/user/list")
public List findAllUser(){
return userRepository.findAll();
}
}
feign-consumer
@FeignClient(value = "USER-SERVICE")
public interface UserService {
@GetMapping("/feign/user/list")
List findAll();
}
使用@FeignClient注解指定服务名来绑定服务,如果不指定服务名,启动项目将会报错。然后创建一个接口与调用普通的service一样调用UserService。
@RestController
public class FeignConsumerController {
@Autowired
private UserService userService;
@GetMapping(value = "/feign/find")
public List findAllUser(){
return userService.findAll();
}
}
最后修改配置文件
spring:
application:
name: feign-consumer
server:
port: 50000
eureka:
client:
service-url:
defaultZone: http://localhost:8888/eureka/
这里使用的User对象与前面ARTICLE-SERVICE的User对象一样。依次启动服务注册中心、服务提供方、服务消费方。然后调用/feign/find接口,可以正常返回数据。
参数绑定
在实际开发中,像上面那种不带参数的接口可能少之又少。Feign提供了多种参数绑定的方式。
在服务提供的UserFeignController中添加以下三个接口:
/**
* 根据id查询用户,将参数包含在Request参数
*/
@GetMapping("/feign/userById")
public User finUserById(@RequestParam Long id){
logger.info(">>>>>>>>>>>id:{}<<<<<<<<<<<<
return userRepository.findOne(id);
}
/**
* 带有Header信息的请求,需要注意的是