zoukankan      html  css  js  c++  java
  • 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类的代码同上面一样,不再展示了
    
  • 相关阅读:
    LinkedList -链表集合
    java包装类,自动装箱,拆箱,以及基本数据类型与字符串的转换
    StringBuilder -字符串缓冲区,节约内层空间变长数组
    System的两常用个静态方法
    StringBuilder
    mysql
    空房间
    数据结构占坑
    sql语句优化
    editPlus快捷键
  • 原文地址:https://www.cnblogs.com/westlin/p/10909799.html
Copyright © 2011-2022 走看看