前面我们花了两篇的时间来写 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/pnotes/251884.html