在介绍 Router Function 之前,我们需要知道 WebFlux 可以运行在 Servlet 3.1 和 Netty 容器之上,所以就需要把这两个容器的不同点抽象出来
ServerRequest <=> HttpServletRequest
ServerResponse <=> HttpServletResponse
开发步骤
- 开发 HandlerFunction,输入 ServerRequest,返回 ServerResponse
- 开发 RouterFunction,请求 URL 和 HandlerFunction 对应起来
- 将 RouterFunction 包装成 HttpHandler,交给 Server 处理
开发 HandlerFunction
@Component
public class UserHandler {
@Resource
private UserRepository userRepository;
/**
* 查询所有用户
*
* @param request request
*/
public Mono<ServerResponse> getAllUser(ServerRequest request) {
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(this.userRepository.findAll(), User.class);
}
/**
* 创建用户
*
* @param request request
*/
public Mono<ServerResponse> createUser(ServerRequest request) {
Mono<User> userMono = request.bodyToMono(User.class);
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(this.userRepository.saveAll(userMono), User.class);
}
/**
* 删除用户
*
* @param request request
*/
public Mono<ServerResponse> deleteUserById(ServerRequest request) {
String id = request.pathVariable("id");
return this.userRepository.findById(id).flatMap(user -> this.userRepository.delete(user))
.then(ServerResponse.ok().build())
.switchIfEmpty(ServerResponse.notFound().build());
}
}
开发 RouterFunction
@Configuration
public class AllRouters {
@Bean
public RouterFunction<ServerResponse> userRouter(UserHandler userHandler) {
return RouterFunctions.nest(
// 相当于类上面的 @RequestMapping("/user")
RequestPredicates.path("/user"),
// 相当于方法上面的 @RequestMapping("/xxx")
RouterFunctions.route(
// 获取全部用户
RequestPredicates.GET("/all"), userHandler::getAllUser)
// 创建用户
.andRoute(RequestPredicates.POST("/create")
.and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), userHandler::createUser)
// 删除用户
.andRoute(RequestPredicates.DELETE("/delete/{id}"), userHandler::deleteUserById)
);
}
}
异常处理
/**
* 创建用户
*
* @param request request
*/
public Mono<ServerResponse> createUser(ServerRequest request) {
Mono<User> userMono = request.bodyToMono(User.class);
// return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
// .body(this.userRepository.saveAll(userMono), User.class);
// User block = request.bodyToMono(User.class).block(); // Spring boot 2.0.1 之后会出现异常
return userMono.flatMap(u -> {
// 校验代码
CheckUtils.checkName(u.getName());
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(this.userRepository.save(u), User.class);
});
}
异常处理切面
@Component
@Order(-99) // 数值越小,优先级越高
public class ExceptionHandler implements WebExceptionHandler {
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
ServerHttpResponse response = exchange.getResponse();
// 设置一个响应头
response.setStatusCode(HttpStatus.BAD_REQUEST);
// 设置返回类型
response.getHeaders().setContentType(MediaType.TEXT_PLAIN);
// 异常信息
String errorMsg = toStr(ex);
DataBuffer dataBuffer = response.bufferFactory().wrap(errorMsg.getBytes());
return response.writeWith(Mono.just(dataBuffer));
}
private String toStr(Throwable ex) {
// 已知异常
if (ex instanceof CheckException) {
CheckException e = (CheckException) ex;
return e.getFiledName() + ": invalid value " + e.getFiledValue();
}
// 未知异常,需要打印堆栈
else {
ex.printStackTrace();
return ex.toString();
}
}
}