依赖

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相同的情况下,其他过滤器会优先执行。


本站总访问量:次本站总访问数:人
本站由 Peng Tong 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。