一、Route
spring:
cloud:
gateway:
routes:
- id: after_route #路由ID需要保证唯一
uri: https://example.org #匹配后路由的服务地址
predicates: #请求转发判断条件
- Path=/admin/** #匹配对应的URL请求,会将匹配到的请求追加到目标uri
- routes指的是配置路由转发规则,可以配置多个路由规则
- 每个route有一个id,标识该路由的唯一性
- uri指请求转发的目标
- predicates指请求转发的判断条件
上述路由配置含义是当我们访问:http://gateway-ip:gateway-port/admin/** 时会被路由到example.org/admin/**
二、Predicate
2.1 Predicate基本用法
Predicate就是一组匹配规则,方便让请求根据匹配到的路由Route进行处理
Predicate介绍:Gateway Predicate
2.2 自定义Predicate Factory
spirng官方为我们提供了许多Predicate Factory能够满足我们日常开发过程中的大部分场景需求,但匹配条件比较复杂时就需要我们自定义实现。
步骤:
- 自定义路由Predicate需要继承AbstractRoutePredicateFactory类,重写apply方法逻辑
- 在apply方法中可获取ServerHttpRequest从而可以获取到请求信息
- 类的命名需要以RoutePredicateFactory结尾,比如RbacAuthRoutePredicateFactory,那么在配置文件中使用时,RbacAuth就是该Predicate Factory的名称
@Component
public class RbacAuthRoutePredicateFactory
extends AbstractRoutePredicateFactory<RbacAuthRoutePredicateFactory.Config> {
public RbacAuthRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return exchange -> {
String requestURI = exchange.getRequest().getURI().getPath();
if (config.getFlag().equals("rbac")
&&(requestURI.startsWith("/sysuser")
||requestURI.startsWith("/sysorg")
||requestURI.startsWith("/sysrole")
||requestURI.startsWith("/sysmenu")
||requestURI.startsWith("/sysdict")
||requestURI.startsWith("/sysapi"))) {
return true; //表示匹配成功
}
return false; //表示匹配失败
};
}
//自定义参数args配置类
public static class Config {
private String flag; //该参数对应配置文件的args
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
}
}
spring:
application:
name: zimug-server-gateway
cloud:
gateway:
routes:
- id: rbsc-service
uri: http://localhost:8401/
predicates:
- name: RbacAuth
args:
flag: rbac
三、Filter
3.1 过滤器简介
通过简介我们知道,gateway内维护了一组过滤器链对请求进行一些过滤操作,比如:鉴权后添加Header携带令牌等。在过滤器中我们可以
- 为请求增加请求头、增加请求参数、增加响应头等功能
- 鉴权、记录审计日志、统计请求响应时长等和具体业务无关的重复性操作。
3.2 过滤器生命周期
Spring Cloud Gateway Filter生命周期:pre和post
- PRE:这种在过滤器请求被路由前调用,可利用这种过滤器实现身份验证、在集群中选择请求的微服务记录调试信息等。
- POST:这种在路由到服务后执行,可用来为响应添加标准的HTTP Header、收集统计信息等
3.3 过滤器分类
Gateway Filter 官方为我们提供了许多过滤器可以修改请求头、参数、路径等操作,一般我们也可以通过自定义过滤器实现这一操作
3.4 自定义全局过滤器
官方为我们提供了许多类型的过滤器,但在实际开发中这些过滤器可能并不能满足我们的实际开发场景,这时我们就需要创建个性化的过滤器实现特定功能。
要实现全局过滤器我们只要实现Global Filter、Order接口重写filter方法即可。
自定义过滤器实现接口耗时统计:
@Slf4j
@Component
public class interfaceTimeStatFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
long startTime = System.currentTimeMillis();
return chain.filter(exchange).then().then(Mono.fromRunnable(() -> {
Long endTime = System.currentTimeMillis();
log.info(exchange.getRequest().getURI().getRawPath() + ", cost time : " + (endTime - startTime) + "ms");
}));
}
@Override
public int getOrder() {
return 0;
}
}
我们通过自定义全局过滤器还可以做许多操作,例如鉴权记录日志等。
3.5 自定义局部过滤器
比如在我们系统中有个别服务是专门为财务专员使用。我们假设有这样的需求,只有指定客户端ip可以访问财务系统。要如何实现呢?
- 自定义Filter工厂需要继承AbstractGatewayFilterFactory类,重写apply方法逻辑
- 在apply中可通过exchage.getRequest拿到ServerHttpRequest对象,从而可以获取请求信息
- 在apply中可通过chain操作过滤器链
- 类的命名需要以GatewayFilterFactory结尾,比如IPForbidGatewayFilterFactory,那么在配置文件中使用该Filter时IPForbid就是这个Filter工厂的名称
- Config类可以定义一个或多个属性,需要重写List shortcutFieldOrder()这个方法指定属性名称
@Component
@Order(99)
public class IPForbidGatewayFilterFactory
extends AbstractGatewayFilterFactory<IPForbidGatewayFilterFactory.Config> {
public IPForbidGatewayFilterFactory()
{
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder()
{
return Arrays.asList("permitIp"); //对应config类的参数
}
@Override
public GatewayFilter apply(Config config)
{
return (exchange, chain) -> {
//获取服务访问的客户端ip
String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
if (config.getPermitIp().equals(ip)) {
//如果客户端ip=permitIp,继续执行过滤器链允许继续访问
return chain.filter(exchange);
}
//否则返回,拒绝请求
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
};
}
static public class Config
{
private String permitIp;
public String getPermitIp() {
return permitIp;
}
public void setPermitIp(String permitIp) {
this.permitIp = permitIp;
}
}
}
配置文件,因为只有一个参数所以图中192.168.1.6 将赋值给config类唯一参数:permitlp
那么如何为GatewayFilterFactory配置多个参数呢?
首先Config要有多个成员变量,如:permitlp、xxx、其次配置文件要进行如下配置
文章参考: