前面我们花了两篇的时间来写 webflux 的 WebFilter,大家应该都明白了它的具体用法。但是最终你会发现,WebFilter 这种过滤器没有servlet filter中的url pattern功能。也就是说它会对所有的 URL 请求进行链接,所以效率就比较低。
而 HandlerFilterFunction 这种用法更加专注具体的过滤细节,更符合 WebFlux 的特点。下面我们一起来学习它!
先来段代码:
@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实现过滤器
原创文章,作者:bd101bd101,如若转载,请注明出处:https://blog.ytso.com/tech/java/251884.html