使用WebFlux的HandlerFilterFunction实现过滤器

前面我们花了两篇的时间来写 webflux 的 WebFilter,大家应该都明白了它的具体用法。但是最终你会发现,WebFilter 这种过滤器没有servlet filter中的url pattern功能。也就是说它会对所有的 URL 请求进行链接,所以效率就比较低。

而 HandlerFilterFunction 这种用法更加专注具体的过滤细节,更符合 WebFlux 的特点。下面我们一起来学习它!

使用WebFlux的HandlerFilterFunction实现过滤器

先来段代码:

@Configuration
public class XttblogWebFlux {

    @Bean
    public RouterFunction<ServerResponse> helloXttblog() {
        return RouterFunctions.route(
                RequestPredicates.GET("/hello").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                request -> ServerResponse.ok().body(BodyInserters.fromObject("Hello www.xttblog")))
                .filter((serverRequest, handlerFunction) -> {
                    // 针对/hello 的请求进行过滤,然后在响应中添加一个Content-Type属性
                    return ServerResponse.status(HttpStatus.OK).header("Content-Type","text/plain; charset=utf-8").build();
                });
    }
}

Router Functions是Spring 5新引入的一套Reactive风格(基于Flux和Mono)的函数式接口,主要包括RouterFunction,HandlerFunction和HandlerFilterFunction,分别对应Spring MVC中的@RequestMapping,@Controller和HandlerInterceptor(或者Servlet规范中的Filter)。

RouterFunctions.route 对针具体 url 进行映射,可以是多个url,多种请求方式:get、post等。匹配到对应的 url 就会路由,否则不会执行路由。

路由器功能映射的路由可以通过调用RouterFunction.filter(HandlerFilterFunction)进行过滤,其中HandlerFilterFunction本质上是一个占用ServerRequest和HandlerFunction的函数,并返回一个ServerResponse。

如果要被多个 HandlerFilterFunction 进行拦截,可以链式调用多次 .filter 方法,具体做法如下:

@Configuration
public class XttblogWebFlux {

    @Bean
    public RouterFunction<ServerResponse> helloXttblog() {
        return RouterFunctions.route(
                RequestPredicates.GET("/hello").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                request -> {
                    System.out.println("url: " + request.attribute("url"));
                    return ServerResponse.ok().body(BodyInserters.fromObject("Hello www.xttblog"));
                })
                .filter((serverRequest, handlerFunction) -> {
                    // 针对/hello 的请求进行过滤,然后在响应中添加一个Content-Type属性
                    return ServerResponse.status(HttpStatus.OK)
                            .header("Content-Type","text/plain; charset=utf-8")
                            .body(BodyInserters.fromObject("Hello www.xttblog.com"));
                });
    }

    @Bean
    public RouterFunction<ServerResponse> xttblog() {
        return RouterFunctions.route(
                RequestPredicates.GET("/xttblog").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                request -> {
                    System.out.println("url: " + request.attribute("url"));
                    return ServerResponse.ok().body(BodyInserters.fromObject("Hello www.xttblog"));
                })
                .filter((serverRequest, handlerFunction) -> {
                    // 这里可以判断是否登录,进行拦截。我这里写个,打个广告
                    if("".equals(serverRequest.path())){
                        return ServerResponse.status(HttpStatus.UNAUTHORIZED).build();
                    }

                    //在request 中放一个url参数
                    serverRequest.attributes().put("url", "www.xttblog.com");
                    // 针对/hello 的请求进行过滤,然后在响应中添加一个Content-Type属性
                    return handlerFunction.handle(serverRequest);
                });
    }

    @Bean
    public RouterFunction<ServerResponse> xttblog_com() {
        return RouterFunctions.route(
                RequestPredicates.GET("/xttblogWebFlux").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                request -> {
                    System.out.println("url: " + request.attribute("url") + ", wexin: " + request.attribute("wexin"));
                    return ServerResponse.ok().body(BodyInserters.fromObject("Hello www.xttblog.com xttblogWebFlux"));
                })
                .filter((serverRequest, handlerFunction) -> {
                    // 这里可以判断是否登录,进行拦截。我这里写个,打个广告
                    if("".equals(serverRequest.path())){
                        return ServerResponse.status(HttpStatus.UNAUTHORIZED).build();
                    }

                    //在request 中放一个url参数
                    serverRequest.attributes().put("url", "www.xttblog.com");
                    // 针对/hello 的请求进行过滤,然后在响应中添加一个Content-Type属性
                    return handlerFunction.handle(serverRequest);
                })
                .filter((serverRequest, handlerFunction) -> {
                    // 这里可以判断是否登录,进行拦截。我这里写个,打个广告
                    if("".equals(serverRequest.path())){
                        return ServerResponse.status(HttpStatus.UNAUTHORIZED).build();
                    }

                    //在request 中放一个url参数
                    serverRequest.attributes().put("wexin", "公众号:[yyucao]");
                    // 针对/hello 的请求进行过滤,然后在响应中添加一个Content-Type属性
                    return handlerFunction.handle(serverRequest);
                });
    }
}

过滤器除了 WebFilter 和 HanderFilterFunction 之外,还可以使用 @ControllerAdvice 或 ServletFilter实现类似的功能。

使用WebFlux的HandlerFilterFunction实现过滤器

: » 使用WebFlux的HandlerFilterFunction实现过滤器

原创文章,作者:bd101bd101,如若转载,请注明出处:https://blog.ytso.com/tech/java/251884.html

(0)
上一篇 2022年5月3日 17:36
下一篇 2022年5月3日 17:40

相关推荐

发表回复

登录后才能评论