springboot webflux 过滤器(使用RouterFunction实现)
作者:o_瓜田李下_o 发布时间:2022-12-12 21:28:44
webflux过滤器(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();
}
}
}
来源:https://blog.csdn.net/weixin_43931625/article/details/106882603


猜你喜欢
- 一、线程的状态NEW: 安排了工作, 还未开始行动RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作.BLOCKED: 这几
- 延迟赋值主要有两点:1.一个参数可能或可能没被赋值.2.一个参数在一个函数中每次使用时可能被赋值.如下面的这种情况:int Add(int
- 我们在设计layout的时候,使用Split视图,就是左侧是代码,右侧是设计图,但是我们忽视了最上方的工具栏,这里才是真正的宝藏。下面教大家
- Java中普通代码块,构造代码块,静态代码块区别及代码示例//执行顺序:(优先级从高到低。)静态代码块>mian方法>构造代码块
- 本文实例讲述了Android编程实现使用webView打开本地html文件的方法。分享给大家供大家参考,具体如下:在布局的配置文件里:<
- zip 是一个非常常见的压缩包格式,本文主要用于说明如何使用代码 文件或文件夹压缩为 zip压缩包及其解压操作,我们采用的是 微软官方的实现
- Shiro 是Shiro 是一个 Apache 下的一开源项目项目,旨在简化身份验证和授权。 1:shiro的配置,通过maven
- “反射”其实就是利用程序集的元数据信息。 反射可以有很多方法,编写程序时请先导入 System.Reflection 命名空间。1、假设你要
- 本文实现android系统照相机的调用来拍照项目的布局相当简单,只有一个Button:<RelativeLayout xmlns:an
- 前言为什么Spring Boot 定时任务是单线程的?想要解释为什么,一定要从源码入手,直接从@EnableScheduling这个注解入手
- Java Socket(套接字)通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过&qu
- 本文实例讲述了Android游戏开发学习②焰火绽放效果实现方法。分享给大家供大家参考。具体如下:本节介绍在游戏开发中常用到的数学物理应用——
- 一、题目描述题目实现:网络通信,实现信息的发送和接收。二、解题思路创建一个服务器类:ServerSocketFrame,继承JFrame类写
- 什么是抽象类什么是抽象类呢?抽象类顾名思义就是很抽象,就是当我们没有足够的信息去描述这个类的时候我们就可以先不用描述,这样的类就是抽象类。用
- 实现效果图:下面是具体代码,可直接复制:package com.lcw.rabbit.widget;import android.anima
- 本文实例讲述了java旋转二维数组的操作,分享给大家供大家参考。具体实现方法如下:package test;/* * &
- 这里主要介绍的是优先队列的二叉堆Java实现,代码如下:package practice;import edu.princeton.cs.a
- 基本功能刚拿到需求,很简单的一个功能,二话不说,很快就出来了:完美!顺利上线!没过几天领导拿着手机过来说:“这一堆数字在一起看着很费劲,像其
- 本文实例为大家分享了java实现银行家算法的具体代码,供大家参考,具体内容如下题目:初始时,Allocate[i,j]=0,表示初始时没有进
- 使用commons的jexl可实现将字符串变成可执行代码的功能,我写了一个类来封装这个功能:import java.util.Map;imp