系列博客
【Spring Cloud一】微服務(wù)基本知識(shí)
【Spring Cloud 三】Eureka服務(wù)注冊與服務(wù)發(fā)現(xiàn)
【Spring Cloud 四】Ribbon負(fù)載均衡
【Spring Cloud 五】OpenFeign服務(wù)調(diào)用
【Spring Cloud 六】Hystrix熔斷
【Spring Cloud 七】Sleuth+Zipkin 鏈路追蹤
背景
在項(xiàng)目中是使用了Gateway做統(tǒng)一的請求的入口,以及統(tǒng)一的跨域處理以及統(tǒng)一的token校驗(yàn)。但是這些工作都是之前的同事來做的,正好在新項(xiàng)目中也需要使用其進(jìn)行統(tǒng)一的token校驗(yàn)。本著對Gateway更精進(jìn)一步所以博主就對Gateway進(jìn)行了較為全面的學(xué)習(xí)了解,包括動(dòng)態(tài)路由、自定義過濾器、token校驗(yàn)和續(xù)活。
一、什么是Spring Cloud Gateway
Spring Cloud Gateway提供一種簡單有效的方法來路由到對應(yīng)的API上,并可以提供一些額外的功能,安全性、監(jiān)控、度量、負(fù)載等等。
我們可以這樣理解,Spring Cloud Gateway將該項(xiàng)目中所有服務(wù)對外提供的API聚集起來,并向外提供唯一的入口,同時(shí)提供了一些額外的功能,安全性、監(jiān)控、度量、負(fù)載等等。
沒使用Spring Cloud Gateway 之前的示意圖:
使用Spring Cloud Gateway之后的示意圖:
二、為什么要使用Spring Cloud Gateway
- 統(tǒng)一入口并解除客戶端與服務(wù)端的耦合:在微服務(wù)架構(gòu)中,每個(gè)微服務(wù)都有自己入口,在沒有它的時(shí)候客戶端需要大量微服務(wù)的地址,會(huì)照成復(fù)雜的客戶端代碼。并且會(huì)暴露服務(wù)端的細(xì)節(jié),如果服務(wù)端發(fā)生變化,可能會(huì)影響到客戶端代碼,導(dǎo)致維護(hù)困難。
- 動(dòng)態(tài)路由和負(fù)載均衡:Spring Cloud GateWay 提供動(dòng)態(tài)路由來應(yīng)對當(dāng);網(wǎng)關(guān)來能夠在多個(gè)服務(wù)實(shí)例之間進(jìn)行負(fù)載均衡,提供整個(gè)系統(tǒng)的高可用。
- 請求過濾:在微服務(wù)架構(gòu)中,可能需要對請求進(jìn)行鑒權(quán)、身份驗(yàn)證一個(gè)中心化的地方來處理這些請求過濾和處理邏輯可以減少重復(fù)的代碼和邏輯。
- 反應(yīng)式和高性能:由于微服務(wù)架構(gòu)的復(fù)雜性,需要一個(gè)能夠處理高并發(fā)請求的解決方案,以確保系統(tǒng)在高負(fù)載情況下保持穩(wěn)定。Spring Cloud Gateway是基于webFlux框架實(shí)現(xiàn)的,而webFlux框架底層使用了高性能Reactor模式通信框架的Netty。
三、 Spring Cloud Gateway 三大核心概念
4.1 Route(路由)
路由是由一個(gè)ID、一個(gè)目的URI、一組斷言、一組Filter組成。
如果路由斷言為真,那么說明這個(gè)路由被匹配上了。
4.2 Predicate(斷言)
是一個(gè)java8函數(shù)斷言。輸入類型是一個(gè)Spring Framewordk ServerWebExchange??梢宰屇闫ヅ銱TTP上的任何請求。比如請求頭和參數(shù)。
4.3 Filter(過濾)
是Spring WebFilter的實(shí)例,Spring Cloud Gateway中的Filter分為兩種,分貝是Gateway Filter和Global Filter(一個(gè)是針對某一個(gè)路由的filter,例如對某一個(gè)接口做限流;一個(gè)是針對全局的filter,例如token校驗(yàn),ip黑名單)。過濾器Filter將會(huì)對請求和響應(yīng)進(jìn)行修改處理。
五、Spring Cloud Gateway是如何工作的
Spring 官網(wǎng)
客戶端向Spring Cloud Gateway發(fā)出請求。如果網(wǎng)關(guān)處理器映射器確定請求與路由匹配,則會(huì)將其發(fā)送到網(wǎng)關(guān)web處理器。它通過特定的過濾器鏈來運(yùn)行請求。過濾器被虛線分割的原因是過濾器可以在發(fā)送代理請求之前和之后運(yùn)行對應(yīng)的邏輯。
四、 如何使用Spring Cloud Gateway進(jìn)行服務(wù)路由
示例項(xiàng)目示意圖:
備注:Eureka的搭建可以參考這篇博客:【Spring Cloud 三】Eureka服務(wù)注冊與服務(wù)發(fā)現(xiàn)
這里之所以使用Eureka是為了之后做動(dòng)態(tài)路由和負(fù)載均衡。
4.1搭建服務(wù)A
pom文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wangwei</groupId>
<artifactId>login-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>login-service</name>
<description>login-service</description>
<properties>
<java.version>8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-redis</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml配置文件
server:
port: 8081
spring:
application:
name: login-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
register-with-eureka: true #設(shè)置為fasle 不往eureka-server注冊,默認(rèn)為true
fetch-registry: true #應(yīng)用是否拉取服務(wù)列表到本地
registry-fetch-interval-seconds: 10 #為了緩解服務(wù)列表的臟讀問題,時(shí)間越短臟讀越少 性能相應(yīng)的消耗回答
instance: #實(shí)例的配置
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
hostname: localhost #主機(jī)名稱或者服務(wù)ip
prefer-ip-address: true #以ip的形式顯示具體的服務(wù)信息
lease-renewal-interval-in-seconds: 10 #服務(wù)實(shí)例的續(xù)約時(shí)間間隔
啟動(dòng)類
@SpringBootApplication
@EnableEurekaClient
public class LoginServiceApplication {
public static void main(String[] args) {
SpringApplication.run(LoginServiceApplication.class, args);
}
}
controller類
@RestController
public class LoginController {
@GetMapping("doLogin")
public String doLogin(){
return "登陸成功";
}
}
4.2 搭建服務(wù)B
pom文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wangwei</groupId>
<artifactId>teacher-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>teacher-service</name>
<description>teacher-service</description>
<properties>
<java.version>8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<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.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml配置文件
server:
port: 8082
spring:
application:
name: teacher-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
register-with-eureka: true #設(shè)置為fasle 不往eureka-server注冊,默認(rèn)為true
fetch-registry: true #應(yīng)用是否拉取服務(wù)列表到本地
registry-fetch-interval-seconds: 10 #為了緩解服務(wù)列表的臟讀問題,時(shí)間越短臟讀越少 性能相應(yīng)的消耗回答
instance: #實(shí)例的配置
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
hostname: localhost #主機(jī)名稱或者服務(wù)ip
prefer-ip-address: true #以ip的形式顯示具體的服務(wù)信息
lease-renewal-interval-in-seconds: 10 #服務(wù)實(shí)例的續(xù)約時(shí)間間隔
啟動(dòng)類
@SpringBootApplication
@EnableEurekaClient
public class TeacherServiceApplication {
public static void main(String[] args) {
SpringApplication.run(TeacherServiceApplication.class, args);
}
}
controller類
@RestController
public class TeacherController {
@GetMapping("teach")
public String teach(){
return "教書學(xué)習(xí)";
}
}
4.3搭建Spring Cloud Gateway服務(wù)
pom文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wangwei</groupId>
<artifactId>gateway-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway-server</name>
<description>gateway-server</description>
<properties>
<java.version>8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-redis</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-redis-reactive</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-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml配置文件
server:
port: 81 #?????80
spring:
application:
name: gateway-server
cloud:
gateway:
enabled: true
routes:
- id: login-service-route # 路由的id 保持唯一
uri: http://localhost:8081 #uri統(tǒng)一資源標(biāo)識(shí)符 url 統(tǒng)一資源定位符
#uri: lb://login-service #??lb負(fù)載均衡
predicates: # 斷言是給某一個(gè)路由來設(shè)定的一種匹配規(guī)則 默認(rèn)不能作用在動(dòng)態(tài)路由上
- Path=/doLogin # 匹配規(guī)則 只要你Path配置上了/doLogin 就往uri轉(zhuǎn)發(fā)并將路徑帶上
- id: teacher-service-route
url: http://localhost:8082
predicates:
- Path=/teach
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
register-with-eureka: true #設(shè)置為fasle 不往eureka-server注冊,默認(rèn)為true
fetch-registry: true #應(yīng)用是否拉取服務(wù)列表到本地
registry-fetch-interval-seconds: 10 #為了緩解服務(wù)列表的臟讀問題,時(shí)間越短臟讀越少 性能相應(yīng)的消耗回答
instance: #實(shí)例的配置
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
hostname: localhost #主機(jī)名稱或者服務(wù)ip
prefer-ip-address: true #以ip的形式顯示具體的服務(wù)信息
lease-renewal-interval-in-seconds: 10 #服務(wù)實(shí)例的續(xù)約時(shí)間間隔
啟動(dòng)類
@SpringBootApplication
@EnableEurekaClient
public class GatewayServerApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServerApplication.class, args);
}
}
4.4啟動(dòng)項(xiàng)目
依次啟動(dòng)Eureka服務(wù),gateway服務(wù)和兩個(gè)服務(wù)A和服務(wù)B。
進(jìn)行調(diào)用服務(wù)A和服務(wù)B:
如下圖所示通過gateway的ip+端口+路徑調(diào)用到對應(yīng)的服務(wù)A中和服務(wù)B中。
4.5動(dòng)態(tài)路由
在微服務(wù)中通常一個(gè)服務(wù)的實(shí)例有多個(gè),那我們網(wǎng)關(guān)如何做負(fù)載均衡呢?
gateway幫我們做了很多東西,只要我們集成注冊中心(nacos、Eureka、zoomkeeper)并添加對應(yīng)的配置gateway就可以自動(dòng)幫我們進(jìn)行負(fù)載均衡。
方式一:
添加對應(yīng)的配置信息,來開啟動(dòng)態(tài)路由
gateway:
enabled: true
routes:
- id: login-service-route # 路由的id 保持唯一
uri: http://localhost:8081 #uri統(tǒng)一資源標(biāo)識(shí)符 url 統(tǒng)一資源定位符
#uri: lb://login-service #??lb負(fù)載均衡
predicates: # 斷言是給某一個(gè)路由來設(shè)定的一種匹配規(guī)則 默認(rèn)不能作用在動(dòng)態(tài)路由上
- Path=/doLogin # 匹配規(guī)則 只要你Path配置上了/doLogin 就往uri轉(zhuǎn)發(fā)并將路徑帶上
- id: teacher-service-route
uri: http://localhost:8082
predicates:
- Path=/teach
discovery:
locator:
enabled: true #開啟動(dòng)態(tài)路由 開啟通過應(yīng)用名稱找到服務(wù)的功能
lower-case-service-id: true # 開啟服務(wù)名稱小寫
請求服務(wù)時(shí)需要帶上對應(yīng)的服務(wù)名稱
方式二:
添加對應(yīng)的配置:uri: lb://login-service #lb負(fù)載均衡
gateway:
enabled: true
routes:
- id: login-service-route # 路由的id 保持唯一
#uri: http://localhost:8081 #uri統(tǒng)一資源標(biāo)識(shí)符 url 統(tǒng)一資源定位符
uri: lb://login-service #lb負(fù)載均衡
predicates: # 斷言是給某一個(gè)路由來設(shè)定的一種匹配規(guī)則 默認(rèn)不能作用在動(dòng)態(tài)路由上
- Path=/doLogin # 匹配規(guī)則 只要你Path配置上了/doLogin 就往uri轉(zhuǎn)發(fā)并將路徑帶上
- id: teacher-service-route
uri: http://localhost:8082
predicates:
- Path=/teach
推薦使用方式一進(jìn)行統(tǒng)一的配置負(fù)載均衡。
五、gateway過濾器
過濾器按照作用范圍可以分為兩種,Gateway Filter和Global Filter。
Gateway Filter:網(wǎng)關(guān)過濾器需要通過 spring.cloud.routes.filters 配置在具體路由下,只作用在當(dāng)前路由上或通過 spring.cloud.default-filters 配置在全局,作用在所有路由上。
Global Filter:全局過濾器,不需要配置路由,系統(tǒng)初始化作用在所有路由上。
全局過濾器一般用于:統(tǒng)計(jì)請求次數(shù)、限流、token校驗(yàn)、ip黑名單攔截等。
5.1自定義全局過濾器
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
/**
* 過濾的方法
* 職責(zé)鏈模式
* 網(wǎng)關(guān)里面有使用 mybatis的二級(jí)緩存有變種職責(zé)鏈模式
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//針對請求的過濾 拿到請求 header url 參數(shù)。。。
ServerHttpRequest request = exchange.getRequest();
//HttpServletRequest 這個(gè)是web里面的
//ServerHttpRequest webFlux里面 響應(yīng)式里面的
String path=request.getURI().getPath();
System.out.println(path);
HttpHeaders headers=request.getHeaders();
System.out.println(headers);
String name = request.getMethod().name();
String hostString = request.getHeaders().getHost().getHostString();
System.out.println(hostString);
//響應(yīng)相關(guān)數(shù)據(jù)
ServerHttpResponse response = exchange.getResponse();
//微服務(wù) 肯定是前后端分離的 一般前后端通過數(shù)據(jù)傳輸是json格式
//{"code":200,"msg":"ok"}
//設(shè)置編碼 響應(yīng)頭
response.getHeaders().set("content-type","application/json;charset=utf-8");
//組裝業(yè)務(wù)返回值
HashMap<String ,Object> map=new HashMap<>(4);
map.put("code", HttpStatus.UNAUTHORIZED.value());
map.put("msg","你未授權(quán)");
ObjectMapper objectMapper=new ObjectMapper();
//把一個(gè)map轉(zhuǎn)換為字節(jié)
byte[] bytes = new byte[0];
try {
bytes = objectMapper.writeValueAsBytes(map);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
//通過buffer工廠將字節(jié)數(shù)組包裝成一個(gè)數(shù)據(jù)報(bào)
DataBuffer wrap = response.bufferFactory().wrap(bytes);
return response.writeWith(Mono.just(wrap));
//放行,到下一個(gè)過濾器
//return chain.filter(exchange);
}
/**
* 制定順序的方法
* 越小越先執(zhí)行
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
請求接口進(jìn)行訪問,可以發(fā)現(xiàn)當(dāng)前請求已經(jīng)被攔截下來。
六、使用gateway做token校驗(yàn)
6.1實(shí)現(xiàn)的大致流程示意圖:
6.2實(shí)現(xiàn)代碼
gateway服務(wù)
pom.xml文件
在pom文件中新增redis的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
注意博主是在本機(jī)安裝的redis所以不需要在服務(wù)中添加對應(yīng)的redis配置。
TokenCheckFilter類
新建TokenCheckFilter類并實(shí)現(xiàn)全局過濾器和Ordered
package com.wangwei.gatewayserver.filter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@Component
public class TokenCheckFilter implements GlobalFilter, Ordered {
/**
* 指定好放行的路徑,白名單
*/
public static final List<String> ALLOW_URL= Arrays.asList("/doLogin","/myUrl");
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 和前端約定好 一般放在請求頭類里面一般key為 Authorization value bearer token
* 1.拿到請求url
* 2.判斷放行
* 3.拿到請求頭
* 4.拿到token
* 5.校驗(yàn)
* 6.放行/攔截
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
if (ALLOW_URL.contains(path)) {
return chain.filter(exchange);
}
//檢查
List<String> authorization = request.getHeaders().get("Authorization");
if (!CollectionUtils.isEmpty(authorization)){
String token = authorization.get(0);
if(StringUtils.hasText(token)){
//約定好的有前綴的bearer token
String realToken = token.replaceFirst("bearer ", "");
if (StringUtils.hasText(realToken)&&redisTemplate.hasKey(realToken)){
return chain.filter(exchange);
}
}
}
//攔截
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().set("content-type","application/json;charset=utf-8");
//組裝業(yè)務(wù)返回值
HashMap<String ,Object> map=new HashMap<>(4);
map.put("code", HttpStatus.UNAUTHORIZED);
map.put("msg","未授權(quán)");
ObjectMapper objectMapper=new ObjectMapper();
//把一個(gè)map轉(zhuǎn)換為字節(jié)
byte[] bytes = new byte[0];
try {
bytes = objectMapper.writeValueAsBytes(map);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
//通過buffer工廠將字節(jié)數(shù)組包裝成一個(gè)數(shù)據(jù)報(bào)
DataBuffer wrap = response.bufferFactory().wrap(bytes);
return response.writeWith(Mono.just(wrap));
}
@Override
public int getOrder() {
return 0;
}
}
login-service服務(wù)
pom.xml文件
在pom文件中新增redis的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
注意博主是在本機(jī)安裝的redis所以不需要在服務(wù)中添加對應(yīng)的redis配置。
LoginController類
在LoginController類中新增doLogin方法
@Autowired
public StringRedisTemplate redisTemplate;
@PostMapping("doLogin")
public String doLogin(@RequestBody User user){
//token
String token= UUID.randomUUID().toString();
//存起來
redisTemplate.opsForValue().set(token,user.toString(), Duration.ofSeconds(7200));
return token;
}
訪問測試
http://localhost:81/doLogin
由于在gateway將該/doLogin放入了白名單,所以該請求不會(huì)進(jìn)行token校驗(yàn),發(fā)送請求成功之后會(huì)返回token
訪問http://localhost:81/teach,并在請求頭中添加token,最后可以看到請求訪問成功。
如果我們不在請求頭中添加對應(yīng)的token或者token為錯(cuò)誤token,那么gateway會(huì)將請求進(jìn)行攔截。
文章來源:http://www.zghlxwxcb.cn/news/detail-653822.html
總結(jié)
- gateway在微服務(wù)中起到了很重要的作用,作為項(xiàng)目請求的統(tǒng)一入口。
- gateway也體現(xiàn)了我們軟件設(shè)計(jì)的復(fù)用思想,可以統(tǒng)一進(jìn)行跨域處理,進(jìn)行token校驗(yàn)。
- gateway比較重要的一塊是關(guān)于他的過濾器,通過實(shí)現(xiàn)過濾器的接口,可以自定義過濾器,提供了很強(qiáng)大的可擴(kuò)展支持
升華
通過學(xué)習(xí)gateway不光是學(xué)習(xí)gateway更重要的是學(xué)習(xí)軟件設(shè)計(jì)思想。文章來源地址http://www.zghlxwxcb.cn/news/detail-653822.html
到了這里,關(guān)于【Spring Cloud 八】Spring Cloud Gateway網(wǎng)關(guān)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!