springboot webflux 过滤器
o_瓜田李下_o 人气:6webflux过滤器(RouterFunction实现)
相关类与接口
HandlerFiterFunction
@FunctionalInterface public interface HandlerFilterFunction<T extends ServerResponse, R extends ServerResponse> { Mono<R> filter(ServerRequest var1, HandlerFunction<T> var2); default HandlerFilterFunction<T, R> andThen(HandlerFilterFunction<T, T> after) { Assert.notNull(after, "HandlerFilterFunction must not be null"); return (request, next) -> { HandlerFunction<T> nextHandler = (handlerRequest) -> { return after.filter(handlerRequest, next); }; return this.filter(request, nextHandler); }; } default HandlerFunction<R> apply(HandlerFunction<T> handler) { Assert.notNull(handler, "HandlerFunction must not be null"); return (request) -> { return this.filter(request, handler); }; } static HandlerFilterFunction<?, ?> ofRequestProcessor(Function<ServerRequest, Mono<ServerRequest>> requestProcessor) { Assert.notNull(requestProcessor, "Function must not be null"); return (request, next) -> { Mono var10000 = (Mono)requestProcessor.apply(request); next.getClass(); return var10000.flatMap(next::handle); }; } static <T extends ServerResponse, R extends ServerResponse> HandlerFilterFunction<T, R> ofResponseProcessor(Function<T, Mono<R>> responseProcessor) { Assert.notNull(responseProcessor, "Function must not be null"); return (request, next) -> { return next.handle(request).flatMap(responseProcessor); }; } }
HandlerFunction
@FunctionalInterface public interface HandlerFunction<T extends ServerResponse> { Mono<T> handle(ServerRequest var1); }
示例
config 层
CustomRouterConfig
@Configuration public class CustomRouterConfig { @Bean public RouterFunction<ServerResponse> initRouterFunction(){ return RouterFunctions.route() .GET("/test/**",serverRequest -> { System.out.println("path:"+serverRequest.exchange().getRequest().getPath().pathWithinApplication().value()); return ServerResponse.ok().bodyValue("hello world"); }) .filter((serverRequest, handlerFunction) -> { System.out.println("custom filter"); return handlerFunction.handle(serverRequest); }) .build(); } }
使用测试
localhost:8080/test/text,控制台输出:
2020-06-21 15:18:08.005 INFO 16336 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2020-06-21 15:18:08.018 INFO 16336 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.807 seconds (JVM running for 2.641)
custom filter
path:/test/text
RouterFunction的webflux
RouterFunction可以运行在servlet或netty上,所以我们需要将两个容器间的不同点抽象出来。
整个开发过程有几步:
1.HandleFunction,实现输入ServerRequest,输出ServerResponse
2.RouterFunction,把请求url和HandlerFunction对应起来
3.把RouterFunction包装成HttpHandler,交给容器Server处理。
代码
实体类和仓库不变
handler:
@Component public class UserHandler { private final UserRepository repository; public UserHandler(UserRepository repository) { this.repository = repository; } public Mono<ServerResponse> getAllUser(ServerRequest request){ return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON) .body(repository.findAll() , User.class); } public Mono<ServerResponse> createUser(ServerRequest request){ Mono<User> userMono = request.bodyToMono(User.class); return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON) .body(repository.saveAll(userMono) , User.class); } public Mono<ServerResponse> deleteUserById(ServerRequest request){ String id = request.pathVariable("id"); return this.repository.findById(id) .flatMap(user -> this.repository.delete(user) .then(ServerResponse.ok().build())) .switchIfEmpty(ServerResponse.notFound().build()); } }
router:
@Configuration public class AllRouters { @Bean RouterFunction<ServerResponse> userRouter(UserHandler handler){ return RouterFunctions.nest( //相当于requestMapping RequestPredicates.path("/user") , RouterFunctions.route(RequestPredicates.GET("/") , handler::getAllUser) .andRoute(RequestPredicates.POST("/").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)) , handler::createUser) .andRoute(RequestPredicates.DELETE("/{id}") , handler::deleteUserById)); } }
接下来看看routerFunction下的参数校验
改造下代码(这里只写一个做例子)
public Mono<ServerResponse> createUser(ServerRequest request){ Mono<User> userMono = request.bodyToMono(User.class); return userMono.flatMap(user -> { //在这里做校验 //xxx return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON) .body(repository.saveAll(userMono) , User.class); }); }
异常捕获,用aop的方式:
@Component @Order(-99) public class ExceptionHandler implements WebExceptionHandler { @Override public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) { ServerHttpResponse response = serverWebExchange.getResponse(); response.setStatusCode(HttpStatus.BAD_REQUEST); response.getHeaders().setContentType(MediaType.TEXT_PLAIN); String errorMsg = toStr(throwable); DataBuffer db = response.bufferFactory().wrap(errorMsg.getBytes()); return response.writeWith(Mono.just(db)); } private String toStr(Throwable throwable) { //已知异常,自定义异常,这里懒得写了,就随便找一个代替 if (throwable instanceof NumberFormatException){ NumberFormatException e = (NumberFormatException) throwable; return e.getMessage(); } //未知异常 else { throwable.printStackTrace(); return throwable.toString(); } } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
加载全部内容