spring webflux filter

    The webfilter model in the spring5 webflux module is similar to other filters or interceptors. Many filters can form a filter chain, and the icon of the filter chain is not drawn.

    The webflux filter currently does not have the url pattern function in the servlet filter. It filters all requests. If you want to implement the url pattern, you can match the url in the filter yourself.

 

The order in which the filters are called

    If there are multiple webflux webfliters, how to determine the order of their calls? The order of calls in the filter chain follows the following rules:

     1. Webfilter implementation classes with @Order annotations are ranked in front of those without this annotation.

     2. For webfliters annotated with @Order, the order value (as a signed int) is ranked first.

     3. For those without the @Order annotation, they are sorted in ascending lexicographical order of the fully qualified class names (including package names) of the implementation classes.

     4. The filter is also a spring bean, which is a singleton in most cases. If it is not a singleton, between these instances

     The call order is estimated to be in chronological order of instantiation.

   

 

  webfliter implementation

  The filter in webflux needs to implement the org.springframework.web.server.WebFilter interface, which has only one method filter.

 

  Two filter implementations: RequestFilter1 and RequestFilter2.

 

  @Component

  @Order(-5)

  public  class RequestFilter1 implements WebFilter {

          @Override

          //Return Mono<Void> to indicate that the processing of this filter has ended.

         public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain)           {

             /*ServerWebExchange寓意交换/兑换(exchange):用请求换回响应. 所以ServerWebExchange包含有成对的http请求对象ServerHttpRequest和http响应对象ServerHttpResponse.

            ServerHttpRequest是webflux controller中的http请求对象,类似webmvc中的HttpServletRequest

           */

            ServerHttpRequest request =  exchange.getRequest();

            ServerHttpResponse response =  exchange.getResponse(); 

 

           //获取请求http头appKey值

           String appKey = request.getHeaders().getFirst("appKey");

           System.out.println("appKey="+appKey);

 

           //添加请求属性key和value

          exchange.getAttributes().put("k1", "v1");

           

           /*过滤器链的概念都是类似的,调用过滤器链的filter方法将请求转到下一个filter,如果该filter是最后一  个filter,那就转到

           该请求对应的handler,也就是controller方法或函数式endpoint */

           return chain.filter(exchange);

        }

    }

}

 

 @Component

 //@Order(1)

 public  class RequestFilter2 implements WebFilter {

    

    @Override

    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

           ServerHttpRequest request =  exchange.getRequest();

           // 获取上个filter设置的属性k1

           String value = (String)exchange.getAttributes().get("k1");

           System.out.println("value="+value);

           return chain.filter(exchange);

        }

    }

}

 

过滤器的通常用法  

 过滤器通常用来实现一些横切的逻辑,例如认证授权、日志记录。

下面的过滤器检查http请求头中是否有token头,如果没有则将请求转到/auth/error,由对应的controller进行处理。

@Component

public  class AuthFilter implements WebFilter {

   

    @Override

    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

           ServerHttpRequest request =  exchange.getRequest();

           //ServerHttpResponse response =  exchange.getResponse(); 

 

           String tokenValue = request.getHeaders().getFirst("token");

           if(null == token){

                /*http头中没有appKey,修改请求的目标url为/auth/error

                  request.mutate返回一个请求构建器(builder design pattern),path方法修改请求的url,build方法返回新的request 

               */ 

               ServerHttpRequest authErrorReq = request.mutate().path("/auth/error").build();

               //erverWebExchange.mutate类似,构建一个新的ServerWebExchange

               ServerWebExchange authErrorExchange =                 exchange.mutate().request(authErrorReq).build();

               return chain.filter(autherrorExchange);

           }

           else{

               return chain.filter(exchange);

           }

        }

    }

 

}

 

 

 

也可在过滤器中直接处理请求,跳过后面的filter和controller

@Component

public  class AuthFilter implements WebFilter {

    @Override

    public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {

           ServerHttpRequest request =  serverWebExchange.getRequest();

           ServerHttpResponse response =  serverWebExchange.getResponse(); 

 

           String tokenValue = request.getHeaders().getFirst("token");

           if(null == token){

                   // 直接返回响应结果,跳过后面的filter和controller

                   response.setStatusCode(HttpStatus.OK);

                   response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

                   return response.writeWith(Mono.just(response.bufferFactory().wrap("{\"msg\":\"no token\"}".getBytes())));

            }

            else {

                return webFilterChain.filter(serverWebExchange);

            }

        }

    }

 

}

 

 

过滤器后处理

前面的演示都还是前处理,在后面的filter完成之后,控制流回到本filter。

可以在WebFilterChain的filter方法后面加入后处理逻辑,这个要熟悉spring reactor3的运算符/算子(operator), 例如doFinally、then、thenEmpty、thenMany、map、flatMap等,后处理逻辑分布在这些运算符中,只要最终返回Mono<Void>即可。

 

@Component

public  class PostProcessingFilter implements WebFilter {

    @Override

    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

        //后处理,打印完成信号的值

        return chain.filter(exchange).doFinally(s ->  System.out.println("signal="+s.toString()));

        

        /* 其他几种

        * or 1: 建议尽量采用链式的fluent连贯写法

        *   Mono<Void>  completeMono = chain.filter(exchange);

        *   return completeMono.doFinally(s -> System.out.println("signal="+s.toString()));

        */

        //or 2: return chain.filter(exchange).thenEmpty(other);

        //or 3: return chain.filter(exchange).thenMany(other).map(..)....then();   

    }

 

}  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326288389&siteId=291194637