在介绍 Router Function 之前,我们需要知道 WebFlux 可以运行在 Servlet 3.1 和 Netty 容器之上,所以就需要把这两个容器的不同点抽象出来

ServerRequest <=> HttpServletRequest
ServerResponse <=> HttpServletResponse

开发步骤

  • 开发 HandlerFunction,输入 ServerRequest,返回 ServerResponse
  • 开发 RouterFunction,请求 URL 和 HandlerFunction 对应起来
  • 将 RouterFunction 包装成 HttpHandler,交给 Server 处理

开发 HandlerFunction

  1. @Component
  2. public class UserHandler {
  3. @Resource
  4. private UserRepository userRepository;
  5. /**
  6. * 查询所有用户
  7. *
  8. * @param request request
  9. */
  10. public Mono<ServerResponse> getAllUser(ServerRequest request) {
  11. return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
  12. .body(this.userRepository.findAll(), User.class);
  13. }
  14. /**
  15. * 创建用户
  16. *
  17. * @param request request
  18. */
  19. public Mono<ServerResponse> createUser(ServerRequest request) {
  20. Mono<User> userMono = request.bodyToMono(User.class);
  21. return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
  22. .body(this.userRepository.saveAll(userMono), User.class);
  23. }
  24. /**
  25. * 删除用户
  26. *
  27. * @param request request
  28. */
  29. public Mono<ServerResponse> deleteUserById(ServerRequest request) {
  30. String id = request.pathVariable("id");
  31. return this.userRepository.findById(id).flatMap(user -> this.userRepository.delete(user))
  32. .then(ServerResponse.ok().build())
  33. .switchIfEmpty(ServerResponse.notFound().build());
  34. }
  35. }

开发 RouterFunction

  1. @Configuration
  2. public class AllRouters {
  3. @Bean
  4. public RouterFunction<ServerResponse> userRouter(UserHandler userHandler) {
  5. return RouterFunctions.nest(
  6. // 相当于类上面的 @RequestMapping("/user")
  7. RequestPredicates.path("/user"),
  8. // 相当于方法上面的 @RequestMapping("/xxx")
  9. RouterFunctions.route(
  10. // 获取全部用户
  11. RequestPredicates.GET("/all"), userHandler::getAllUser)
  12. // 创建用户
  13. .andRoute(RequestPredicates.POST("/create")
  14. .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), userHandler::createUser)
  15. // 删除用户
  16. .andRoute(RequestPredicates.DELETE("/delete/{id}"), userHandler::deleteUserById)
  17. );
  18. }
  19. }

异常处理

  1. /**
  2. * 创建用户
  3. *
  4. * @param request request
  5. */
  6. public Mono<ServerResponse> createUser(ServerRequest request) {
  7. Mono<User> userMono = request.bodyToMono(User.class);
  8. // return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
  9. // .body(this.userRepository.saveAll(userMono), User.class);
  10. // User block = request.bodyToMono(User.class).block(); // Spring boot 2.0.1 之后会出现异常
  11. return userMono.flatMap(u -> {
  12. // 校验代码
  13. CheckUtils.checkName(u.getName());
  14. return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
  15. .body(this.userRepository.save(u), User.class);
  16. });
  17. }

异常处理切面

  1. @Component
  2. @Order(-99) // 数值越小,优先级越高
  3. public class ExceptionHandler implements WebExceptionHandler {
  4. @Override
  5. public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
  6. ServerHttpResponse response = exchange.getResponse();
  7. // 设置一个响应头
  8. response.setStatusCode(HttpStatus.BAD_REQUEST);
  9. // 设置返回类型
  10. response.getHeaders().setContentType(MediaType.TEXT_PLAIN);
  11. // 异常信息
  12. String errorMsg = toStr(ex);
  13. DataBuffer dataBuffer = response.bufferFactory().wrap(errorMsg.getBytes());
  14. return response.writeWith(Mono.just(dataBuffer));
  15. }
  16. private String toStr(Throwable ex) {
  17. // 已知异常
  18. if (ex instanceof CheckException) {
  19. CheckException e = (CheckException) ex;
  20. return e.getFiledName() + ": invalid value " + e.getFiledValue();
  21. }
  22. // 未知异常,需要打印堆栈
  23. else {
  24. ex.printStackTrace();
  25. return ex.toString();
  26. }
  27. }
  28. }