一,前言
使用RestTemplate實(shí)現(xiàn)Rest API調(diào)用時(shí),我們是使用拼接字符串的方式拼接URL的,URL中如果有參數(shù)而且參數(shù)比較多,這就變得難以維護(hù)。
二,F(xiàn)eign簡介
Feign是Netflix開發(fā)的聲明式、模板化的Http客戶端,其靈感來自Retrofit、JAXRS-2.0以及WebSocket。Feign可以更便捷、優(yōu)雅的調(diào)用Http API
在Spring Cloud中使用Feign非常簡單,創(chuàng)建一個(gè)接口,并在接口上添加注解就完成了。
Feign支持多種注解,F(xiàn)eign自帶的或JAX-RS注解等。
Spring Cloud對(duì)Feign進(jìn)行了增強(qiáng),使Feign支持了SpringMVC注解,并整合了Ribbon和Eureka,從而讓Feign的使用更加方便。
三,為消費(fèi)者整合Feign
1,添加Feign依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
2,創(chuàng)建Feign接口,并添加@FeignClient注解
/**
Feign客戶端接口
@author yebin
@date 2020/12/8 10:44
-
@since 1.0.1
*/
@FeignClient(name = "movie-provider")
public interface UserFeignClient {@RequestMapping(value = "/{id}",method = RequestMethod.GET)
public User findById(@PathVariable("id") Long id);
}
3,修改Controller及啟動(dòng)類
@RestController
@Slf4j
public class UserController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@Autowired //注入負(fù)載均衡客戶端
private LoadBalancerClient loadBalancerClient;
@Autowired
private UserFeignClient userFeignClient;
//feign方式調(diào)用
@GetMapping("/user/feign/{id}")
public User findByIdFeign(@PathVariable Long id) {
return this.userFeignClient.findById(id);
}
//restTemplate方式調(diào)用
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
return this.restTemplate.getForObject("http://movie-provider:8091/" + id, User.class);
}
@GetMapping("/user/list")
public List<User> findAll() {
return restTemplate.getForObject("http://movie-provider:8091/list", List.class);
}
/**
* 獲取提供者元數(shù)據(jù)信息
* @return
*/
@GetMapping("/provider/instance")
public List<ServiceInstance> getServiceInstance(){
return discoveryClient.getInstances("movie-provider");
}
/**
* 打印當(dāng)前選擇的是哪個(gè)節(jié)點(diǎn)
* 注意:
* 不能將restTemplate.getForObject()與loadBalancerClient.choose()寫在一個(gè)方法中,兩者會(huì)引起沖突,因?yàn)榇a中restTemplate實(shí)際上
* 是一個(gè)Ribbon客戶端,本身已經(jīng)包含了choose行為。
*/
@GetMapping("/print-instance")
public void printInstance(){
ServiceInstance serviceInstance = loadBalancerClient.choose("movie-provider");
log.info("serviceId--->{},host--->{},port--->{}",serviceInstance.getServiceId(),serviceInstance.getHost(),serviceInstance.getPort());
}
}
/**
1,@EnableDiscoveryClient 聲明這是一個(gè)Eureka Client,此處可用@EnableEurekaClient代替。
2,spring cloud 中服務(wù)發(fā)現(xiàn)組件有多種,如:Zookeeper,Consul等,@EnableDiscoveryClient為各種組件提供了支持。
3,@EnableDiscoveryClient是spring-cloud-commons項(xiàng)目的注解,是一個(gè)高度的抽象。
-
4,@EnableEurekaClient表明是Eureka 的Client,該注解是是spring-cloud-netflix項(xiàng)目的,只能與Eureka一起工作。
*/
@EnableDiscoveryClient
//@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients //啟用Feign客戶端
public class MovieConsumerFeignApplication {@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}public static void main(String[] args) {
SpringApplication.run(MovieConsumerFeignApplication.class, args);
}
}
4,自定義Feign配置


/**
Feign自定義配置類
Feign配置類不應(yīng)放在與啟動(dòng)類同一個(gè)包下,否則該類中的配置信息就會(huì)被所有@FeignClient共享,或者顯式指定
@ComponetScan不掃描@Configuration所在的包
@author yebin
@date 2020/12/8 11:06
-
@since 1.0.1
*/
@Configuration
public class FeignConfiguration {//將契約改為feign原生的契約,這樣可以使用feign自帶的注解了。
@Bean
public Contract feignContract(){
return new feign.Contract.Default();
}
}
5,F(xiàn)eign對(duì)繼承的支持
Feign支持繼承,可將一些公共操作抽到父接口中,以簡化Feign的操作。

6,F(xiàn)eign對(duì)壓縮的支持
一些場景下需要對(duì)請(qǐng)求或響應(yīng)進(jìn)行壓縮,此時(shí)可以使用以下屬性來啟用Feign的壓縮功能。
feign.compression.request.enable=true
feign.compression.response.enable=true
對(duì)于請(qǐng)求的壓縮,F(xiàn)eign還可以更為詳細(xì)的設(shè)置:
feign.compression.request.enable=true
支持的媒體類型
feign.compression.request.mime-types=text/xml,application/xml,application/json
請(qǐng)求的最小閾值,默認(rèn)是2048
feign.compression.request.min-request-size=2048
7,F(xiàn)eign的日志
Feign對(duì)日志處理非常靈活,可為每個(gè)Feign客戶端指定日志記錄策略,每個(gè)Feign客戶端都會(huì)記錄一個(gè)logger。默認(rèn)情況下,logger的名稱是Feign接口的完事類名,需要注意的是Feign的日志只會(huì)對(duì)DEBUG級(jí)別日志做出響應(yīng)。

7.1 Feign的配置類
/**
- Feign自定義配置類
- Feign配置類不應(yīng)放在與啟動(dòng)類同一個(gè)包下,否則該類中的配置信息就會(huì)被所有@FeignClient共享,或者顯式指定
- @ComponetScan不掃描@Configuration所在的包
- @author yebin
- @date 2020/12/8 11:06
- @since 1.0.1
*/
@Configuration
public class FeignConfiguration {
//Feign日志
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
8,使用Feign構(gòu)造多請(qǐng)求的參數(shù)
Spring Cloud為Feign添加了Spring MVC注解的支持,可以使用參照Spring MVC注解的方式來構(gòu)造多請(qǐng)求參數(shù)
GET請(qǐng)求:
8.1
@Configuration
public class FeignConfiguration {
@GetMapping("/get")
public User get(@RequestParam("id") Long id,@RequestParam("username") String username){
...
}
}
POST請(qǐng)求:
@RestController
@Slf4j
public class UserController {
@PostMapping("/post")
public User post(@RequestBody User user){
return null;
}
}