目录
1. 概念
在Spring社区是这么介绍Gateway的:
该项目提供了一个库,用于在 Spring WebFlux 或 Spring WebMVC 之上构建 API 网关。Spring Cloud Gateway 旨在提供一种简单而有效的方法来路由到 API,并为它们提供横切关注点,例如:安全性、监控/指标和弹性。
Spring Cloud Gateway 功能:
- 基于 Spring Framework 和 Spring Boot 构建
- 能够匹配任何请求属性上的路由。
- 谓词和筛选器特定于路由。
- 断路器集成。
- Spring Cloud Discovery客户端集成
- 易于编写谓词和过滤器
- 请求速率限制
- 路径重写
2. 使用方法
2.1 导入依赖
父模块版本控制:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
子模块依赖导入:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
2.2 配置相关属性
server:
#端口号
port: 9000
spring:
application:
#微服务名称
name: gateway-api
cloud:
gateway:
#网关将处理的路由列表
routes:
#此路由的唯一标识
- id: user-api
#应将请求转发到目标微服务的地址
uri: http://localhost:7001
#处理此路由必须满足的条件
predicates:
- #请求路径必须满足Path的条件才应用此路由
- Path=/user-service/**
#请求或响应的操作
filters:
#值为1的筛选器,意味着在转发请求路径之前从请求路径中删除一个段
- StripPrefix=1
去除端口号配置和微服务名称配置,其余的需转移到nacos配置中心里,此处为方便展示将其放入appliction.yml文件中;
2.2.1 重点属性的作用及其使用方法
- url=http://localhost:7001:
实际上,此处的配置其实并不灵活,属于硬编码,也没有考虑到负载均衡的问题,为了解决这个问题,实际配置应该为:url:lb://微服务名称;这样,哪怕修改了微服务端口号,只要服务名称不变,网关还是能够转发请求到指定的微服务中去,也解决了负载均衡的问题(使用此方法还需将gateway服务注册到nacos中,代码如下)
- -Path=/user-service/**:请求路径必须有相对应的前缀才能应用此路由(例如:/user-service/user1),在配置多个路由时, 路径前缀不能重复,如有重复的前面匹配上了,后面的配置则不会生效
- StripPrefix=1: 内置筛选器,当服务器不需要网关所配置的路径前缀时,使用该属性进行剔除,值为1,则去除请求路径第一个前缀,以此类推
2.2.2 内置断言
在2.2.1中所标注的重点属性有一个Path,这其实是网关断言中的其中一个,因其应用次数是最频繁的,所以将其放在重点属性中描述;其余断言,应用的较为广泛的在以下图片中
3. gateway跨域
在网关的配置文件中加入这段属性即可
spring:
cloud:
gateway:
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
- "http://www.leyou.com"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
4. 自定义全局过滤器
在实际项目中,避免不了权限控制,但是在每一个微服务中都加入权限控制的代码又会造成大量的代码冗余;因此,需要在网关中添加一个全局过滤器进行全局的权限控制
package com.bdqn.qianmo.gateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @program: cloud-demo
* @description: 自定义全局过滤器
* @author: QianMo
* @create: 2024-01-09 14:59
**/
@Configuration
public class AuthGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if(StringUtils.isEmpty(token)){
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().add("Content-Type","application/json;charset=utf-8");
String message = "{\"尚未登录!\"}";
//包装字符串的字节来创建一个DateBuffer对象,该方法用于将字符串转换为字节数组
DataBuffer wrap = response.bufferFactory().wrap(message.getBytes());
return response.writeWith(Mono.just(wrap));
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
此代码为实例代码,根据实际需求进行改造实现权限控制功能