Spring Cloud Feign的使用和自定義配置

Java EE 目錄:https://blog.csdn.net/dkbnull/article/details/87932809
Spring Cloud 專欄:https://blog.csdn.net/dkbnull/column/info/36820


在上一篇文章 Spring Cloud自定義Eureka Ribbon負載均衡策略 中,我們使用Ribbon自定義的策略實現了負載均衡,接下來我們介紹下Spring Cloud的另一種服務調用方式Feign

0. 開發環境

  • IDE:IntelliJ IDEA 2017.1 x64

  • jdk:1.8.0_91

  • Spring Boot:2.1.1.RELEASE

  • Spring Cloud:Finchley.RELEASE


1. Feign簡介

Feign是一個聲明式的僞Http Web服務客戶端,它使得寫Http客戶端變得非常簡單。使用Feign,只需創建一個接口並註解,就可實現服務間調用。它具有可插拔的註解特性,支持使用Feign註解、JAX-RS註解、Spring MVC註解。Feign默認集成了Ribbon,並結合了Eureka,默認實現了負載均衡。

2. 新建Feign服務消費者

2.1 新建Feign服務消費者

在這裏插入圖片描述

2.2 引入依賴

<?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">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>spring-boot-consumer-feign</artifactId>
    <packaging>jar</packaging>

    <parent>
        <artifactId>spring-cloud-demo</artifactId>
        <groupId>cn.wbnull</groupId>
        <version>1.0.0</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
</project>

2.3 新建application.yml

server:
  port: 8084
  servlet:
    context-path: /springbootconsumer

spring:
  application:
    name: spring-boot-consumer-feign

eureka:
  client:
    register-with-eureka: false
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8090/springcloudeureka/eureka/

2.4 新建Spring Boot啓動類

這裏要注意,啓動類需增加類註解 @EnableFeignClients,表示此項目爲Feign客戶端

package cn.wbnull.springbootconsumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class SpringBootConsumerFeignApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootConsumerFeignApplication.class, args);
    }
}

2.5 定義Feign接口

cn.wbnull.springbootconsumer包下新建feign包,再新建GatewayFeignClient接口類

  • @FeignClient(“服務id名稱”),表示調用哪個服務
  • @GetMapping(value = “接口地址”),表示調用哪個接口。這裏要注意接口地址要保留server.servlet.context-path部分,沒有則省略
package cn.wbnull.springbootconsumer.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient("spring-boot-provider")
public interface GatewayFeignClient {

    @GetMapping(value = "/springbootprovider/gateway")
    String gateway() throws Exception;
}

2.6 新建控制器類

cn.wbnull.springbootconsumer包下新建controller包,再新建GatewayController類

package cn.wbnull.springbootconsumer.controller;

import cn.wbnull.springbootconsumer.feign.GatewayFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Scope("prototype")
public class GatewayController {

    @Autowired
    private GatewayFeignClient gatewayFeignClient;

    @GetMapping(value = "/gateway")
    public String gateway() throws Exception {
        return gatewayFeignClient.gateway();
    }
}

這裏@Autowired GatewayFeignClient可能會有報錯,是因爲這個Bean是程序啓動時注入的,現在編譯器還無法裝配,可以不用管,啓動程序不會報錯。但是如果看着報錯不順眼非要去掉,可以在剛纔的GatewayFeignClient接口類增加@Component註解。

2.7 測試

依次啓動spring-cloud-eureka,spring-boot-provider,spring-boot-provider-v2,spring-boot-consumer-feign。然後瀏覽器訪問http://127.0.0.1:8084/springbootconsumer/gateway,不斷刷新,可以到到返回信息正常,且 hello world,this is spring-boot-providerhello world,this is spring-boot-provider-v2 交替出現。
在這裏插入圖片描述
在這裏插入圖片描述

2.8 增加傳參接口

剛纔我們服務消費者調用服務提供者的接口,都是沒有參數的,下面我們新建一個帶參數的接口進行測試。

2.8.1 修改spring-boot-provider

spring-boot-provider服務GatewayController類增加如下代碼

    @PostMapping(value = "/user")
    public String user(@RequestParam(value = "name") String name) throws Exception {
        return "hello world,this is spring-boot-provider. name is " + name;
    }

2.8.2 修改spring-boot-provider-v2

spring-boot-provider-v2服務GatewayController類增加如下代碼

    @PostMapping(value = "/user")
    public String user(@RequestParam(value = "name") String name) throws Exception {
        return "hello world,this is spring-boot-provider-v2. name is " + name;
    }

2.8.3修改spring-boot-consumer-feign

1、spring-boot-consumer-feign服務GatewayFeignClient類增加如下代碼

    @PostMapping(value = "/springbootprovider/user")
    String user(@RequestParam(value = "name") String name) throws Exception;

2、spring-boot-consumer-feign服務GatewayController類增加如下代碼

    @PostMapping(value = "/user")
    public String user(@RequestParam(value = "name") String name) throws Exception {
        return gatewayFeignClient.user(name);
    }

2.8.4 測試

依次啓動spring-cloud-eureka,spring-boot-provider,spring-boot-provider-v2,spring-boot-consumer-feign。然後打開Postman,配置如下,不斷點擊Send按鈕,可以看到返回信息正常,且 hello world,this is spring-boot-provider. name is 測試namehello world,this is spring-boot-provider-v2. name is 測試name 交替出現。
在這裏插入圖片描述
在這裏插入圖片描述

3. 自定義Feign配置

上篇我們自定義Ribbon負載均衡策略時,會出現包掃描的問題,Feign自定義配置也同樣存在這個問題,這裏我們不再贅述,直接使用註解 @ComponentScan 自定義掃描類。但是與上篇不同,我們這裏自定義一個註解,當Java類使用了該註解時,@ComponentScan就會忽略掃描。

cn.wbnull.springbootconsumer包下新建config包,再新建ComponentScanExclude註解類

package cn.wbnull.springbootconsumer.config;

public @interface ComponentScanExclude {
}

3.1 自定義配置類

config包下新建GlobalConfiguration類

package cn.wbnull.springbootconsumer.config;

import feign.Contract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScanExclude
public class GlobalConfiguration {

    @Bean
    public Contract GlobalContract() {
        return new Contract.Default();
    }
}

3.1.1 Contract

我們可以看到 GlobalConfiguration 類的 GlobalContract() 方法返回了一個 Contract 對象,Contract 表示契約,說白了,就是一個註解解釋器。前面我們說過,Feign支持使用Feign註解、JAX-RS註解、Spring MVC註解。Contract 可以幫助我們將這些註解解釋成Feign能夠理解的Http請求。我們也可以通過自定義一個Contract 解釋器來實現我們自己的註解,這個放到後面介紹,本篇不做贅述。

Feign一開始默認使用的契約是Spring MVC,所以我們前面測試使用的都是Spring MVC註解。但現在我們return new Contract.Default(),Contract.Default()默認使用的契約是Feign,所以我們也對應的要修改成Feign註解。

3.2 加載自定義配置

修改GatewayFeignClient類,@FeignClient 註解引入自定義配置類,並且將接口註解修改成Feign註解

package cn.wbnull.springbootconsumer.feign;

import cn.wbnull.springbootconsumer.config.GlobalConfiguration;
import feign.Param;
import feign.RequestLine;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;

@Component
@FeignClient(value = "spring-boot-provider", configuration = GlobalConfiguration.class)
public interface GatewayFeignClient {

    @RequestLine("GET /springbootprovider/gateway")
    String gateway() throws Exception;

    @RequestLine("POST /springbootprovider/user?name={name}")
    String user(@Param("name") String name) throws Exception;
}

3.3 測試

依次啓動spring-cloud-eureka,spring-boot-provider,spring-boot-provider-v2,spring-boot-consumer-feign。然後瀏覽器訪問http://127.0.0.1:8084/springbootconsumer/gateway,不斷刷新,跟剛纔測試結果相同;Postman配置跟剛纔一樣,不斷點擊Send,跟剛纔測試結果相同。

3.4 增加application/json方式傳參接口

下面我們再新建一個application/json方式傳參的接口進行測試。

3.4.1 修改spring-boot-provider

spring-boot-provider服務GatewayController類增加如下代碼

    @PostMapping(value = "/users")
    public Map<String, String> users(@RequestBody Map<String, String> request) throws Exception {
        request.put("hello world", "spring-boot-provider");

        return request;
    }

3.4.2 修改spring-boot-provider-v2

spring-boot-provider-v2服務GatewayController類增加如下代碼

    @PostMapping(value = "/users")
    public Map<String, String> users(@RequestBody Map<String, String> request) throws Exception {
        request.put("hello world", "spring-boot-provider-v2");

        return request;
    }

3.4.3修改spring-boot-consumer-feign

1、spring-boot-consumer-feign服務GatewayFeignClient類增加如下代碼

    @RequestLine("POST /springbootprovider/users")
    @Headers("Content-Type: application/json")
    String users(Map<String, String> request) throws Exception;

2、spring-boot-consumer-feign服務GatewayController類增加如下代碼

    @PostMapping(value = "/users")
    public String users(@RequestBody Map<String, String> request) throws Exception {
        return gatewayFeignClient.users(request);
    }

2.8.4 測試

依次啓動spring-cloud-eureka,spring-boot-provider,spring-boot-provider-v2,spring-boot-consumer-feign。然後打開Postman,配置如下,不斷點擊Send按鈕,可以看到返回信息正常,且兩組返回信息交替出現。
在這裏插入圖片描述
在這裏插入圖片描述





GitHub:https://github.com/dkbnull/SpringCloudDemo
微信:




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章