spring cloud gateway 自定義GatewayFilterFactory


spring cloud gateway提供了很多內置的過濾器,那么因為需求的關系,需要自定義實現,並且要可配置,在一番折騰之后,總算是解決了,那么久記錄下來

對於自定義的factory,我們可以選擇去實現接口或繼承已有的抽象類,相關的接口是GatewayFilterFactory,而springboot默認幫我們實現的抽象類是AbstractGatewayFilterFactory這個

首先來看我們的自定義的過濾器工廠類代碼

/**
 * Description: it's purpose...
 *
 * @author a 2019-5-22
 * @version 1.0
 */
public class ExampleGatewayFilterFactory extends AbstractGatewayFilterFactory<ExampleGatewayFilterFactory.Config> {

    /**
     * 定義可以再yaml中聲明的屬性變量
     */
    private static final String TYPE = "type";
    private static final String OP = "op";

    /**
     * constructor
     */
    public ExampleGatewayFilterFactory(){
        // 這里需要將自定義的config傳過去,否則會報告ClassCastException
        super(Config.class);
    }


    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(TYPE, OP);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return ((exchange, chain) -> {
            boolean root = "root".equals(config.getOp());
            if (root){
                LogUtil.info("GatewayFilter root");
            }
            else {
                LogUtil.info("GatewayFilter customer");
            }
            // 在then方法里的,相當於aop中的后置通知
            return chain.filter(exchange).then(Mono.fromRunnable(()->{
                // do something
            }));
        });
    }

    /**
     * 自定義的config類,用來設置傳入的參數
     */
    public static class Config {

        /**
         * 過濾類型
         */
        private String type;

        /**
         * 操作
         */
        private String op;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getOp() {
            return op;
        }

        public void setOp(String op) {
            this.op = op;
        }
    }
}

因為我使用的是springboot,那么需要在啟動類里,將這個工廠注入到spring容器當中

@Bean
public ExampleGatewayFilterFactory exampleGatewayFilterFactory(){
    return new ExampleGatewayFilterFactory();
}

然后是yaml的配置,這里需要注意的是,之前我一直失敗,在調用gateway會報告找不到對應的過濾率,這是因為命名導致的
springboot約定過濾器的前綴為配置的name,而后面最好統一都是GatewayFilterFactory

spring:
  application:
    name: demo-gateway
  cloud:
    gateway:
      routes:
        - id: custom
          uri: lb://demo-consumer
          predicates:
            - Path=/account/v1/**
          filters:
            - name: Example
              args:
                op: root
                type: he

到這里,過濾器的編寫與配置就完成了,然后啟動項目,訪問/account/v1/test,就會在日志里看到在過濾器中打印的信息了

注意我們通過這種工廠創建出來的過濾器是沒有指定order的,會被默認設置為是0,配置在yml文件中,則按照它書寫的順序來執行
如果想要在代碼中設置好它的順序,工廠的apply方法需要做一些修改

@Override
    public GatewayFilter apply(Config config) {
        return new InnerFilter(config);
    }

    /**
     * 創建一個內部類,來實現2個接口,指定順序
     */
    private class InnerFilter implements GatewayFilter, Ordered {

        private Config config;

        InnerFilter(Config config) {
            this.config = config;
        }

        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            System.out.println("  pre 自定義過濾器工廠 AAAA  " + this.getClass().getSimpleName());
            boolean root = "root".equals(config.getOp());
            if (root) {
                System.out.println("  is root ");
            } else {
                System.out.println("  is no root ");
            }
            // 在then方法里的,相當於aop中的后置通知
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                System.out.println("  post 自定義過濾器工廠 AAAA " + this.getClass().getSimpleName());
            }));
        }

        @Override
        public int getOrder() {
            return -100;
        }
    }

    // config類的代碼同上面一樣,不再展示了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM