Spring Cloud Gateway配置过滤器
依赖
1 2 3 4 5 6 7 8
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
|
这里引入两个依赖,spring-cloud-dependencies使用Greenwich.SR2版本,第一个依赖及引入gateway的功能,第二个依赖引入的actuator是为了方便查看gateway的路由配置
配置
1 2 3 4 5 6 7 8 9 10
| spring: gateway: discovery: locator: enabled: true management: endpoints: web: exposure: include: "*"
|
第一个配置是允许gateway发现所有在nacos上注册的服务,前提是gateway也注册在该nacos上,第二配置是为了打开actuator的功能,具体我也不太清楚。
代码
通过实现GatewayFilter设置过滤器
过滤器类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class AuthGatewayFilter implements GatewayFilter, Ordered {
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("请求前执行的语句"); return chain.filter(exchange).then( Mono.fromRunnable(() -> log.info("请求后执行的语句")) ); }
@Override public int getOrder() { return 0; } }
|
这里只写了两条日志打印语句,是为了强调在chain.filter(exchange).then()外部的程序实在请求转发之前运行的,既“pre”, Mono.fromRunnable()方法内部的程序是在请求处理完之后运行的,既“post”。也可以直接返回chain.filter(exchange);,则表示不对请求完之后的事件进行处理。这里同样实现了Ordered是为了是指定滤器的执行顺序,order越小越先执行,这里要强调一下,过滤器的order和路由的order不是一回事
配置过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @SpringBootApplication public class GatewayApplication {
public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); }
@Bean public RouteLocator routeLocator(RouteLocatorBuilder builder) { return builder.routes() .route(r -> r.path("/producer/**") .filters(f -> f.stripPrefix(1) .filters(new AuthGatewayFilter()) ) .uri("lb://producer") ) .build(); }
}
|
这里通过配置RouteLocator使AuthGatewayFilter过滤器生效,这里的f.stripPrefix(1)是设置路径切割的,既切掉头部1(既设置的参数)个字段,如果不设置则转发将会变为/producer/producer/。
效果图

我们通过访问/actuator/gateway/routes可以看到,我们设置的过滤器已经在第一个路由中生效了,并且在路由列表第一个。
通过实现AbstractGatewayFilterFactory设置过滤器
过滤器类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| @Slf4j @Component public class AuthGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthGatewayFilterFactory.Config> {
public AuthGatewayFilterFactory(){ super(Config.class); }
@Override public GatewayFilter apply(Config config) { log.info(config.getKey()); return (exchange, chain) -> { log.info("请求前执行的语句"); return chain.filter(exchange).then( Mono.fromRunnable(() -> log.info("请求后执行的语句")) ); }; }
@Override public List<String> shortcutFieldOrder() { return Arrays.asList("key"); }
@Data static class Config{ private String key; }
}
|
可以看到apply方法返回的是一个GatewayFilter对象,所以也可以直接返回我们上面实现的AuthGatewayFilter对象。注意:在类的构造器中一定要调用下父类的构造器把Config类型传过去,否则会报ClassCastException。shortcutFieldOrder方法也要实现就是将config中的参数添加到列表,这样才能从配置文件读数据。还有一点,这里的config不能用内部类,原因不明,可以静态内部类
配置过滤器
1 2 3 4 5 6 7 8 9 10 11 12
| spring: cloud: gateway: routes: - id: auth_route uri: lb://producer predicates: - Path=/producer/** filters: - StripPrefix=1 - Auth order: -1
|
配置与上面在启动类里面的RouteLocator配置没有什么区别,但是多了一个order: -1,下面看一下order: -1的效果
- 不配置order: -1

我们可以看到自定义的auth_route在列表最后一列,而第2个route是gateway默认配置的,就是由最上面的写的那个enabled: true配置产生的,它的predicates与我们自定义的predicates是一样的,所以我们自定义的route根本不会生效
- 配置order: -1

我们可以看到,auth_route已经在列表第一项了,这样gateway默认配置的与auth_route的predicates一样的route就失效了。当然我这里只是强调order的作用,实际上不会这么写。而且我们发现上面通过RouteLocator配置的route直接在列表的第一项,并没有配置order,这应该和gateway内部的配置有关
全局过滤器
上面两个过滤器都是局部过滤器,全局过滤器比较简单,只要实现GlobalFilter就行了,写法与上面的实现的AuthGatewayFilter一样,区别是只要在全局过滤器类上加上@Component即可生效。最后强调一下,全局过滤器在与其他过滤器order相同的情况下,其他过滤器会优先执行。