使用Feign實(shí)現(xiàn)聲明式Rest調(diào)用

一,前言
使用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配置


image.png

image.png

/**

  • 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的操作。


image.png

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)。


image.png
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;
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容