在介绍 Router Function 之前,我们需要知道 WebFlux 可以运行在 Servlet 3.1 和 Netty 容器之上,所以就需要把这两个容器的不同点抽象出来
ServerRequest <=> HttpServletRequest
ServerResponse <=> HttpServletResponse
开发步骤
- 开发 HandlerFunction,输入 ServerRequest,返回 ServerResponse
- 开发 RouterFunction,请求 URL 和 HandlerFunction 对应起来
- 将 RouterFunction 包装成 HttpHandler,交给 Server 处理
开发 HandlerFunction
@Componentpublic class UserHandler {@Resourceprivate 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
@Configurationpublic class AllRouters {@Beanpublic 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 {@Overridepublic 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();}}}
