Spring Cloud alibaba之Feign

JAVA項(xiàng)目中如何實(shí)現(xiàn)接口調(diào)用?

  1. Httpclient
    Httpclient是Apache Jakarta Common下的子項(xiàng)目,用來提供高效的、最新的、功能豐富的支持Http協(xié)議的客戶端編程工具包,并且它支持HTTP協(xié)議最新版本和建議。HttpClient相比傳統(tǒng)JDK自帶的URL Connection,提升了易用性和靈活性,是客戶端發(fā)送HTTP請(qǐng)求變得容易,提高了開發(fā)的效率。
  2. Okhttp
    一個(gè)處理網(wǎng)絡(luò)請(qǐng)求的開源項(xiàng)目,是安卓端最火的輕量級(jí)框架,由Square公司貢獻(xiàn),用于代替HttpUrlConnection和Apache HttpClient。OkHttp擁有簡(jiǎn)潔的API、高校的性能,并支持多種協(xié)議(HTTP/2和SPDY)
  3. HttpURLConnection
    HttpURLConnection是Java的標(biāo)準(zhǔn)類,它繼承自URLConnection,可用于向指定網(wǎng)站發(fā)送GET請(qǐng)求、POST請(qǐng)求。HttpURLConection使用比較復(fù)雜,不想HttpClient那樣容易使用。
  4. RestTemplate WbClient
    RestTemplate是Spring提供的用于訪問Rest服務(wù)的客戶端,RestTemplate提供了多種便捷訪問遠(yuǎn)程HTTP服務(wù)的方法,能夠大大提高客戶端的編寫效率。

上面介紹的是最常見的幾種調(diào)用接口的方法,我們下面介紹的方法比上面的更簡(jiǎn)單、方便,它就是Feign。

什么是Feign

Feign是Nexflix開發(fā)的聲明式、模板化的HTTP客戶端,其靈感來自Retrofit、JAXRS-2.0以及WebSocket。Feign可幫助我們更加便捷、優(yōu)雅地調(diào)用HTTP API。
\color{#FF0000}{Spring Cloud openfeign對(duì)Feign進(jìn)行了增強(qiáng),使其支持Spring MVC注解,另外還整合了Ribbon和Nacos,從而使得Feign的使用更加方便。}

優(yōu)勢(shì)

Feign可以做到\color{#FF0000}{使用HTTP請(qǐng)求遠(yuǎn)程服務(wù)時(shí)就像調(diào)用本地方法一樣的體驗(yàn)},開發(fā)者完全感知不到這是遠(yuǎn)程方法,更感知不到這是個(gè)HTTP請(qǐng)求。它像Dubbo一樣,consumer直接調(diào)用接口方法調(diào)用provider,而不是要通過常規(guī)的HttpClient構(gòu)造請(qǐng)求解析返回?cái)?shù)據(jù)。它解決了讓開發(fā)者調(diào)用遠(yuǎn)程接口就跟調(diào)用本地方法一樣,無需關(guān)注與遠(yuǎn)程的交互細(xì)節(jié),更無需關(guān)注分布式環(huán)境開發(fā)。(簡(jiǎn)單地說就是A服務(wù)的Service接口去調(diào)用別的B服務(wù)的Controller接口)

Spring Cloud Alibaba快速整合Opne Feign

  1. 復(fù)制order-nacos項(xiàng)目,修改項(xiàng)目名為order-openfeign,修改其它配置。引入依賴
<!--openfeign遠(yuǎn)程調(diào)用-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 新建Feign接口
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

/*
name指定遠(yuǎn)程調(diào)用的接口所對(duì)應(yīng)的服務(wù)名
path指定遠(yuǎn)程調(diào)用的接口所對(duì)應(yīng)的類的@RequestMapping
 */
@FeignClient(name = "stock-service", path = "/stock")
public interface StockFeignService {
    @RequestMapping("/reduct")
    String reduct();
}
  1. 編寫訂單Controller
import com.mrZhao.feign.StockFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    StockFeignService stockFeignService;

    @RequestMapping("/add")
    public String add() {
        System.out.println("下單成功!");
        String reduct = stockFeignService.reduct();
        return "Hello Feign" + reduct;
    }
}
  1. 此時(shí)stockFeignService下面有一條紅色的波浪線,需要在啟動(dòng)類中配置上開啟Feign的注解
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

最終項(xiàng)目結(jié)構(gòu)


訪問訂單接口


日志配置

1.新建product-nacos子項(xiàng)目,controller

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/product")
public class ProductController {
    @Value("${server.port}")
    String port;

    @RequestMapping("/{id}")
    public String get(@PathVariable Integer id) {
        System.out.println("查詢商品" + id);
        return "查詢商品" + id + ":" + port;
    }
}

application.yml

server:
  port: 8007
spring:
  application:
    name: product-nacos
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        username: nacos
        password: nacos
        namespace: public

最終長(zhǎng)這樣


  1. 在上文中創(chuàng)建的order-openfeign項(xiàng)目中新建配置類
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 趙毅梵
 * @create 2022-04-21
 */
// 此處配置Configuration注解會(huì)全局生效 如果想指定對(duì)一個(gè)的微服務(wù)生效 就不能配置
@Configuration
public class FeignConfig {
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
  1. 新建feign接口
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/*
name指定遠(yuǎn)程調(diào)用的接口所對(duì)應(yīng)的服務(wù)名
path指定遠(yuǎn)程調(diào)用的接口所對(duì)應(yīng)的類的@RequestMapping
 */
@FeignClient(name = "product-nacos", path = "/product")
public interface ProductFeignService {
    @RequestMapping("/{id}")
    String get(@PathVariable("id") Integer id);
}
  1. 更新Controller
import com.mrZhao.feign.ProductFeignService;
import com.mrZhao.feign.StockFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    StockFeignService stockFeignService;

    @Autowired
    ProductFeignService productFeignService;

    @RequestMapping("/add")
    public String add() {
        System.out.println("下單成功!");
        String reduct = stockFeignService.reduct();
        String s = productFeignService.get(1);
        return "Hello Feign" + reduct + s;
    }
}
  1. application.yml添加配置
# springboot默認(rèn)的日志級(jí)別時(shí)info feign默認(rèn)的是debug 所以日志級(jí)別不輸出
logging:
  level:
    com.mrZhao.feign: debug
  1. 啟動(dòng)訂單服務(wù)、庫(kù)存服務(wù)和商品服務(wù),訪問訂單接口



    日志信息也打印到了控制臺(tái)


契約配置

??Spring Cloud在Feign的基礎(chǔ)上做了擴(kuò)展,使用Spring MVC的疏解來完成Feign的功能。原生的Feign是不支持Spring MVC注解的,如果你想在Spring Cloud中使用原生的注解方式來定義客戶端也是可以的,通過配置契約來改變這個(gè)配置,Spring Cloud中默認(rèn)的是SpringMvcContract。
??Spring Cloud 1早期版本就是用的原生Feign,隨著netflix的停更替換成了Open feign。

  1. 修改契約配置,支持Feign原生的注解
/**
  *  修改契約配置,支持feign原生的注解
  *  @return
  */
@Bean
public Contract feignContract() {
  return new Cotract.Default();
}

$\color{#FF0000}{注意:修改契約配置后,stock-service不再支持springmvc的注解,需要使用Feign原生的注解}

  1. OrderFeignService中配置使用Feign原生的注解
@FeignClient(name = "stock-service", path = "/stock", configuration = FeignConfig.class)
public interface StockFeignService {
    @RequestLine("GET /reduct")
    String reduct();
}
  1. 補(bǔ)充:也可以通過yml方式配置契約
# feign日志局部配置
feign:
  client:
    config:
      stock-service:
        loggerLevel: BASIC
        # 設(shè)置未默認(rèn)的契約(還原成原生注解)
        contract: feign.Contract.Default

超時(shí)時(shí)間設(shè)置

通過 Options 可以配置連接超時(shí)時(shí)間和讀取超時(shí)時(shí)間,Options 得第一個(gè)參數(shù)是連接的超時(shí)時(shí)間(ms),默認(rèn)值是2s;第二個(gè)是請(qǐng)求處理的超時(shí)時(shí)間(ms),默認(rèn)是5s。
全局配置

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

// 此處配置Configuration注解會(huì)全局生效 如果想指定對(duì)一個(gè)的微服務(wù)生效 就不能加
@Configuration
public class FeignConfig {
    @Bean
    public Request.Options options() {
        return new Request.Options(5000, 10000);
    }
}

yml中配置

# feign日志局部配置
feign:
  client:
    config:
      stock-service:
        loggerLevel: BASIC
        # 連接超時(shí)時(shí)間,默認(rèn)是2s
        connectTimeout: 5000
        # 請(qǐng)求處理超時(shí)時(shí)間,默認(rèn)是5s
        readTimeout: 3000

\color{#FF0000}{補(bǔ)充說明:Feign的底層用的是Ribbon,但超時(shí)時(shí)間以Feign配置為準(zhǔn)}
測(cè)試超時(shí)情況:

?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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