06.Spring Cloud學習筆記之宣告式服務呼叫元件Feign
前言
Spring Cloud Feign基於Netflix Feign實現,整合了Spring Cloud Ribbon與Spring Cloud Hystrix,除了提供這兩者的強大功能外,還提供了一種宣告式的Web服務客戶端定義方式,我們可以做到使用HTTP請求遠端服務時能與呼叫本地方法一樣的編碼體驗,讓開發者在開發過程中感知不到這是個HTTP請求
快速入門
在pom.xml檔案中匯入如下依賴
<?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>
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId >com.roberto.springcloud</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>spring-cloud-movie-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
</dependencies>
</project>
在啟動類新增@EnableFeignClients開啟Spring Cloud Feign的支援
package com.roberto.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@EnableEurekaClient
@EnableFeignClients
@SpringBootApplication
public class SpringCloudMovieService {
public static void main(String args[]) {
SpringApplication.run(SpringCloudMovieService.class, args);
}
}
定義Service介面,通過@FeignClient註解指定服務名來繫結服務,然後使用SpringMVC的註解來繫結具體服務提供的REST介面
package com.roberto.springcloud.feign;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(name = "USER-SERVICE")
public interface UserFeignClient {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
String index();
}
此處USER-SERVICE為服務名 且/hello介面返回Hello World
在Controller層注入Feign介面進行呼叫
package com.roberto.springcloud.controller;
import com.roberto.springcloud.feign.UserFeignClient;
import com.roberto.springcloud.feign.UserFeignClient2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MovieController {
@Autowired
private UserFeignClient userFeignClient;
@RequestMapping(value = "/index", method = RequestMethod.GET)
public String index() {
return userFeignClient.index();
}
}
application.yml檔案配置如下
spring:
application:
name: movie-service
server:
port: 9092
eureka:
client:
healthcheck:
enabled: true
serviceUrl:
defaultZone: http://roberto:[email protected]:8761/eureka
instance:
prefer-ip-address: true
呼叫/index介面檢視結果
Feign引數繫結
新建User實體類
package com.roberto.springcloud.entity;
public class User {
private String username;
private String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
修改USER-SERVICE服務的介面
package com.roberto.springcloud.controller;
import com.roberto.springcloud.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
public class UserController {
@RequestMapping(value = "hello", method = RequestMethod.GET)
public String hello(@RequestParam String username) {
return "Hello " + username;
}
@RequestMapping(value = "hello2", method = RequestMethod.GET)
public User hello(@RequestHeader String username, @RequestHeader String password) {
return new User(username, password);
}
@RequestMapping(value = "hello3", method = RequestMethod.POST)
public User hello(@RequestBody User user) {
return user;
}
}
修改UserFeignClient介面
package com.roberto.springcloud.feign;
import com.roberto.springcloud.entity.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.*;
@FeignClient(name = "USER-SERVICE")
public interface UserFeignClient {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
String hello(@RequestParam("username") String username);
@RequestMapping(value = "/hello2", method = RequestMethod.GET)
User hello(@RequestHeader("username") String username, @RequestHeader("password") String password);
@RequestMapping(value = "/hello3", method = RequestMethod.POST)
User hello(@RequestBody User user);
}
注:在定義各引數繫結時,@RequestParam和@RequestHeader等可以指定引數名稱的註解,他們的value千萬不能省略,在SpringMVC中這些註解會根據引數名作為預設值但在Feign中必須顯示指定,否則會丟擲異常
在Controller中新增測試介面進行測試
package com.roberto.springcloud.controller;
import com.roberto.springcloud.entity.User;
import com.roberto.springcloud.feign.UserFeignClient;
import com.roberto.springcloud.feign.UserFeignClient2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MovieController {
@Autowired
private UserFeignClient userFeignClient;
@RequestMapping(value = "helloTest", method = RequestMethod.GET)
public String helloTest() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(userFeignClient.hello("RobertoHuang")).append("\n");
stringBuffer.append(userFeignClient.hello("RobertoHuang","123456")).append("\n");
stringBuffer.append(userFeignClient.hello(new User("RobertoHuang","123456"))).append("\n");
return stringBuffer.toString();
}
}
訪問/helloTest介面檢視輸出結果
Feign繼承特性
在使用SpringMVC的註解來繫結服務介面時,我們幾乎完全可以從服務提供方的Controller中依靠複製操作,構建出相應的服務客戶端繫結介面,既然存在這麼多複製操作,我們可以把相同的部分進行抽象以減少編碼量,下面我們對上面工程進行改造
新建USER-API工程,在pom.xml檔案中匯入如下依賴
<?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>
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.roberto.springcloud</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>spring-cloud-user-api</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
在USER-API工程中新建User類
package com.roberto.springcloud.entity;
public class User {
private String usernamne;
private String password;
public User() {
}
public User(String usernamne, String password) {
this.usernamne = usernamne;
this.password = password;
}
public String getUsernamne() {
return usernamne;
}
public void setUsernamne(String usernamne) {
this.usernamne = usernamne;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"usernamne='" + usernamne + '\'' +
", password='" + password + '\'' +
'}';
}
}
在USER-API工程中新建UserServiceApi類
package com.roberto.springcloud.api;
import com.roberto.springcloud.entity.User;
import org.springframework.web.bind.annotation.*;
public interface UserServiceApi {
@RequestMapping(value = "hello", method = RequestMethod.GET)
String hello(@RequestParam("username") String username);
@RequestMapping(value = "hello2", method = RequestMethod.GET)
User hello(@RequestHeader("username") String username, @RequestHeader("password") String password);
@RequestMapping(value = "hello3", method = RequestMethod.POST)
User hello(@RequestBody User user);
}
在USER-SERVICE的pom檔案新增USER-API的依賴
<dependency>
<groupId>com.roberto.springcloud</groupId>
<artifactId>spring-cloud-user-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
修改USER-SERVICE的UserController
package com.roberto.springcloud.controller;
import com.roberto.springcloud.api.UserServiceApi;
import com.roberto.springcloud.entity.User;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController implements UserServiceApi {
@Override
public String hello(@RequestParam String username) {
return "Hello " + username;
}
@Override
public User hello(@RequestHeader String username, @RequestHeader String password) {
return new User(username, password);
}
@Override
public User hello(@RequestBody User user) {
return user;
}
}
在服務呼叫方的pom檔案新增USER-API的依賴
<dependency>
<groupId>com.roberto.springcloud</groupId>
<artifactId>spring-cloud-user-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
修改服務呼叫者的UserFeignClient
package com.roberto.springcloud.feign;
import com.roberto.springcloud.api.UserServiceApi;
import org.springframework.cloud.netflix.feign.FeignClient;
@FeignClient(name = "USER-SERVICE")
public interface UserFeignClient extends UserServiceApi{
}
訪問/helloTest介面檢視輸出結果
Feign日誌配置
Spring Cloud Feign在構建被@FeignClient註解修飾的服務客戶端時,會為每一個客戶端建立一個feign.Logger例項,我們可以配置修改日誌列印級別,在application.yml檔案中新增如下配置
logging:
level:
com.roberto.springcloud.feign: debug
如果只配置瞭如上內容是無法打印出Feign的日誌的,因為Feign客戶端預設的Logger.Level物件定義為NONE級別,該級別不會記錄任何Feign呼叫過程中的資訊,所以我們需要調整它的級別,針對全域性日誌級別,在主類或配置類中直接加入Logger.Level的Bean建立,具體如下:
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
測試結果如下
Feign的Logger級別主要提供了下面4類,可根據實際情況調整使用
NONE:不記錄任何資訊
BASIC:僅記錄請求方法、URL以及響應狀態和時間
HEADERS:除了記錄BASIC級別的資訊外,還會記錄請求和響應的頭資訊
FULL:記錄所有請求與響應的明細,包括頭資訊、請求體、元資料等
Feign請求壓縮
Spring Cloud Feign支援對請求與響應進行GZIP壓縮,以減少通訊過程中的效能損耗,我們只需要通過如下兩個引數進行設定,就能開啟請求與響應壓縮的功能
feign.compression.request.enabled=true
feign.compression.response.enabled=true
同時我們還能對請求壓縮做一些更細緻的設定,比如下面的配置內容指定了壓縮的請求資料型別,並設定了請求壓縮的大小下限,只有超過這個大小的請求才會對其進行壓縮
feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048
上述配置的mime-types與min-request-size均為預設值
相關推薦
06.Spring Cloud學習筆記之宣告式服務呼叫元件Feign
前言 Spring Cloud Feign基於Netflix Feign實現,整合了Spring Cloud Ribbon與Spring Cloud Hystrix,除了提供這兩者的強大功能外,還提供了一種宣告式的Web服務客戶端定義方式,我們可以做到使用HT
Spring Cloud學習筆記之Eureka Server註冊中心
Eureka Server提供服務註冊服務,各個節點啟動後,會在Eureka Server中進行註冊,這樣EurekaServer中的服務登錄檔中將會儲存所有可用服務節點的資訊,服務節點的資訊可以在介面中直觀的看到。我們簡單實現一下Eureka Server。 1.新建一個Maven專案
Spring Cloud學習筆記之Eureka框架的原理
Eureka 服務發現與註冊:我們在呼叫微服務的時候,如果我們的微服務部署了多份,我們應該如何去呼叫?這裡就涉及到了服務發現與註冊。服務發現就是程式如何通過一個標誌來獲取服務列表,並且這個服務列表是能夠隨著服務的狀態而動態變更的。 Spring Cloud提供了多種註冊中心的支援:如Eur
Spring Cloud學習筆記之微服務實現(一)(Spring Boot+IDEA)
我們先使用Spring Boot實現一個微服務,業務非常簡單: 1.商品微服務,通過商品id查詢商品的微服務 2.訂單微服務,通過訂單id查詢訂單資料,同時需要呼叫商品微服務查詢出訂單詳情資料對應的商品資料。 說明: 1.對於商品微服務而言,商品微服務是服務的提供者,訂單微服務是服務的消費
Spring Cloud學習筆記之微服務實現(二)(Spring Boot+Spring Cloud+IDEA)
在【Spring Cloud學習筆記之微服務實現(一)】中,我們實現了微服務,但是在實際的專案中,我們需要實現動態訪問微服務,在此之前,已經介紹了Spring Cloud和Eureka,並且實現了eureka註冊中心。現在我們實現一下動態呼叫。 注:註冊中心的服務在此期間保持啟動狀態。
03.Spring Cloud學習筆記之服務註冊與服務發現元件Eureka
前言 從本篇部落格開始將正式進入Spring Cloud的實戰部分,因為博主用了很長時間的Dubbo,並且Spring Cloud和Dubbo都是微服務框架,它們有很多相似之處,所以可能在部落格中提及進行類比,如果沒有接觸過Dubbo的朋友直接略過該部分內容即
幹貨分享微服務spring-cloud(5.聲明式服務調用feign)
ace request pre sha 通過 san rest process white Spring cloud feign基於Netflix feign實現,整合了spring cloud ribbon與spring cloud hystrix,除了提供這兩者的強大功
Spring Cloud學習筆記 【篇一:分布式配置中心 Spring Colud Config】
16px gin war imp web項目 tps conf name request 一、簡介 Spring Cloud Config提供了在分布式系統的外部配置的客戶端支持。通過配置服務(Config Server)來為所有的環境和應用提供外部配置的集中管理。這些概念
Sprng Cloud學習筆記之Spring Cloud簡介
Spring Cloud Spring Cloud是一系列框架的有序集合(Spring Cloud並不是一個專案,它是一套專案的組合)。它利用Spring Boot的開發便利性巧妙地簡化了分散式系統基礎設施的開發,如服務發現註冊、配置中心、訊息匯流排、負載均衡、斷路器、資料監控等,都可以
Spring Cloud學習筆記(三)——服務發現與消費之使用Ribbon
服務消費一般使用ribbon和feign兩種方式。而feign實際上也是以ribbon為基礎的。有多個服務提供者例項的情況下ribbon可以實現負載均衡。 1.pom檔案:這裡與服務提供者不同的是需要引入ribbon包。 <dependency>
Spring Cloud學習筆記(四)——服務發現與消費之使用Feign
Feign 是一個宣告web服務客戶端,這便得編寫web服務客戶端更容易,使用Feign 建立一個介面並對它進行註解,它具有可插拔的註解支援包括Feign註解與JAX-RS註解,Feign還支援可插拔的編碼器與解碼器,Spring Cloud 增加了對 Spring MVC的
Spring Cloud 之 宣告式REST客戶端 Feign元件
Feign是一個宣告式的Web服務客戶端。能很簡單的呼叫其他服務的API。並且實現負載均衡。 1、建立Feign模組 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http:/
spring cloud學習筆記3(同步呼叫、非同步呼叫、響應式呼叫)
1.同步呼叫 同步呼叫,在學習筆記2就是同步呼叫 2.非同步呼叫 修改service package com.study.cloud.consumer.services; import com.netflix.hystrix.contrib.javanica.annot
Spring Cloud Eureka 分散式開發之服務註冊中心、負載均衡、宣告式服務呼叫實現
介紹 本示例主要介紹 Spring Cloud 系列中的 Eureka,使你能快速上手負載均衡、宣告式服務、服務註冊中心等 Eureka Server Eureka 是 Netflix 的子模組,它是一個基於 REST 的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移。 服務註冊和發現對於微服務架
我的第一個spring boot程序(spring boot 學習筆記之二)
獲取json 了解 訪問 static 依賴 過程 public 獲取數據 gap 第一個spring boot程序 寫在前面:鑒於spring註解以及springMVC的配置有大量細節和知識點,在學習理解之後,我們將直接進入spring boot的學習,在後續學習中用到註
Spring Cloud學習筆記-003
開發 spring pre 學習筆記 bubuko lse 參數 穩定 觸發 Spring Cloud學習筆記-003 服務提供者:向註冊中心註冊服務 1. 新建maven工程,骨架選擇quickstart,工程名稱:demo-member 2. 加入相關依賴
Spring Cloud學習筆記-004
服務 微服務架構 裏的 url 文件 啟動 spa 實現 ron 高可用註冊中心 在微服務架構這樣的分布式環境中,需要充分考慮發生故障的情況,所以在生產環境中必須對各個組件進行高可用部署,對於微服務如此,對於服務註冊中心也一樣。如果一直使用單節點的服務註冊中心
Spring Cloud學習筆記-007
通過 cati tar source 復雜 members quest 項目 ati 聲明式服務調用:Spring Cloud Feign Feign基於Netflix Feign實現,整合了Spring Cloud Ribbon和Spring Cloud H
Spring Cloud學習筆記-011
設備 配置文件 enable 環境 共享 app 啟用 .config localhost 分布式配置中心:安全保護 由於配置中心存儲的內容比較敏感,做一定的安全處理是必需的。為配置中心實現安全保護的方式有很多,比如物理網絡限制、OAuth2授權等。由於微服務
Spring Cloud學習筆記-012
目錄 註冊中心 image yml 接口 面向 基礎 collect 16px 分布式服務跟蹤:Spring Cloud Sleuth 隨著業務的發展,系統規模也會變得越來越大,各微服務間的調用關系也變得越來越錯綜復雜。通常一個由客戶端發起的請求在後端系統中會