Java基础、中级、高级、架构面试资料

使用WebFlux的HandlerFilterFunction实现过滤器

JAVA herman 8334浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云

前面我们花了两篇的时间来写 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实现类似的功能。

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » 使用WebFlux的HandlerFilterFunction实现过滤器