天天看點

gateway 過濾器執行順序_spring boot gateway 過濾器的執行順序

前言

學習官方文檔,發現對于過濾器有分為三類

預設過濾器

自定義過濾

全局過濾器

于是就有一個疑問,關于這些過濾器的通路順序是怎樣的,今天就以一個demo來進行測試

準備階段

過濾器工廠類

以此為模闆,複制出幾份就可以了,注意列印資訊,可區分就行

public class ExampleGatewayFilterFactory extends AbstractGatewayFilterFactory {

private int order;

public ExampleGatewayFilterFactory(int order) {

this.order = order;

}

@Override

public GatewayFilter apply(Object config) {

return new InnerFilter();

}

private class InnerFilter implements GatewayFilter, Ordered {

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

System.out.println(" pre 自定義過濾器工廠 " + this.getClass().getSimpleName());

// 在then方法裡的,相當于aop中的後置通知

return chain.filter(exchange).then(Mono.fromRunnable(() -> {

System.out.println(" post 自定義過濾器工廠 " + this.getClass().getSimpleName());

}));

}

@Override

public int getOrder() {

return order;

}

}

}

過濾器配置類

這裡我們設定了

2個預設過濾器

2個自定義過濾器,

1個全局過濾器

@SpringBootConfiguration

public class FilterConfig {

// 以下是全局的過濾器(注意這裡我們保持它為最高優先級)

@Bean

@Order(value = Ordered.HIGHEST_PRECEDENCE)

public GlobalFilter costFilter(){

return new CostFilter();

}

// 以下是自定義的的過濾器工廠

@Bean

public GatewayFilterFactory exampleAGatewayFilterFactory(){

return new ExampleAGatewayFilterFactory(0);

}

@Bean

public GatewayFilterFactory exampleGatewayFilterFactory(){

return new ExampleGatewayFilterFactory(1);

}

// 以下是預設過濾工廠

@Bean

public GatewayFilterFactory myDefaultGatewayFilterFactory(){

return new MyDefaultGatewayFilterFactory(2);

}

@Bean

public GatewayFilterFactory myDefaultAAGatewayFilterFactory(){

return new MyDefaultAAGatewayFilterFactory(3);

}

}

springboot啟動類

// 這裡掃描基礎包,可以把其他配置加入進來

@SpringBootApplication(scanBasePackages = {"com.example.gateway"})

public class GatewayApplication {

public static void main(String[] args) {

SpringApplication.run(GatewayApplication.class, args);

}

}

application.yml檔案的配置

spring:

application:

name: demo-gateway

cloud:

gateway:

discovery:

locator:

enabled: true

routes:

- id: to-route

uri: lb://demo-consumer

# 例如通路 localhost:8080/route會路由到demo-consumer的服務下的/route接口

predicates:

- Path=/route

- id: to-account

uri: lb://demo-consumer

predicates:

- Path=/account/v1/**

filters:

- name: ExampleA

- name: Example

# 預設過濾器

default-filters:

- name: MyDefaultAA

- name: MyDefault

測試

場景一

按照準備階段的配置order順序,來看通路的結果

pre 自定義過濾器工廠 AAAA InnerFilter

pre 自定義過濾器工廠 InnerFilter

pre 【預設】過濾器工廠 InnerFilter

pre 【預設AAA】過濾器工廠 InnerFilter

pre 全局過濾器 CostFilter

post 全局過濾器 CostFilter

post 【預設AAA】過濾器工廠 InnerFilter

post 【預設】過濾器工廠 InnerFilter

post 自定義過濾器工廠 InnerFilter

post 自定義過濾器工廠 AAAA InnerFilter

過濾器的執行順序與堆棧這個資料結構很想,LIFO,gateway中的過濾器隻有前置和後置2個生命周期,pre中後觸發的,在post中就先被執行了

從輸出的列印來看,預設過濾器和自定義的過濾器按照我們定義的1 2 3 4的順序,成功的列印了出來,而全局過濾器是在最後才執行

場景二

自定義過濾器和預設過濾器都保留為相同的order順序

修改如下,都統一為是0

@Bean

public GatewayFilterFactory exampleAGatewayFilterFactory(){

return new ExampleAGatewayFilterFactory(0);

}

@Bean

public GatewayFilterFactory exampleGatewayFilterFactory(){

return new ExampleGatewayFilterFactory(0);

}

// 以下是預設過濾工廠

@Bean

public GatewayFilterFactory myDefaultGatewayFilterFactory(){

return new MyDefaultGatewayFilterFactory(0);

}

@Bean

public GatewayFilterFactory myDefaultAAGatewayFilterFactory(){

return new MyDefaultAAGatewayFilterFactory(0);

}

傳回的結果

pre 【預設AAA】過濾器工廠 InnerFilter

pre 【預設】過濾器工廠 InnerFilter

pre 自定義過濾器工廠 AAAA InnerFilter

pre 自定義過濾器工廠 InnerFilter

pre 全局過濾器 CostFilter

post 全局過濾器 CostFilter

post 自定義過濾器工廠 InnerFilter

post 自定義過濾器工廠 AAAA InnerFilter

post 【預設】過濾器工廠 InnerFilter

post 【預設AAA】過濾器工廠 InnerFilter

注意到我們前面在yml中配置的過濾器的順序是

filters:

- name: ExampleA

- name: Example

# 預設過濾器

default-filters:

- name: MyDefaultAA

- name: MyDefault

這與前面幾行的輸出結果一緻,是以如果當優先order一樣的前提下,預設過濾器的執行優先于自定義過濾器,過濾器的執行順序是與你在yml中聲明的順序是一緻的。

全局過濾器依然是最後一個執行的

場景三

我們将自定義過濾器和預設過濾的順序按照穿插的來,即

自定義、預設、自定義、預設

// 以下是自定義的的過濾器工廠

@Bean

public GatewayFilterFactory exampleAGatewayFilterFactory(){

return new ExampleAGatewayFilterFactory(1);

}

@Bean

public GatewayFilterFactory exampleGatewayFilterFactory(){

return new ExampleGatewayFilterFactory(3);

}

// 以下是預設過濾工廠

@Bean

public GatewayFilterFactory myDefaultGatewayFilterFactory(){

return new MyDefaultGatewayFilterFactory(2);

}

@Bean

public GatewayFilterFactory myDefaultAAGatewayFilterFactory(){

return new MyDefaultAAGatewayFilterFactory(4);

}

運作通路後的執行結果如下

pre 自定義過濾器工廠 AAAA InnerFilter

pre 【預設】過濾器工廠 InnerFilter

pre 自定義過濾器工廠 InnerFilter

pre 【預設AAA】過濾器工廠 InnerFilter

pre 全局過濾器 CostFilter

post 全局過濾器 CostFilter

post 【預設AAA】過濾器工廠 InnerFilter

post 自定義過濾器工廠 InnerFilter

post 【預設】過濾器工廠 InnerFilter

post 自定義過濾器工廠 AAAA InnerFilter

可以看到它是按照我們書寫的順序來的

結論

全局過濾器與其他2類過濾器相比,永遠是最後執行的;它的優先級隻對其他全局過濾器起作用

當預設過濾器與自定義過濾器的優先級一樣時,優先出發預設過濾器,然後才是自定義過濾器;同類型的過濾器,出發順序與他們在配置檔案中聲明的順序一緻

預設過濾器與自定義過濾器使用同樣的order順序空間,即他們會按照各自的順序來進行排序