From a2824323b1ee8e7c577444362e0a1cf2aa209fff Mon Sep 17 00:00:00 2001
From: YunaiV <>
Date: Mon, 25 Nov 2019 01:52:32 +0800
Subject: [PATCH] =?UTF-8?q?spring=20webflux=20=E5=AE=9E=E7=8E=B0=E5=85=A8?=
=?UTF-8?q?=E5=B1=80=E7=BB=9F=E4=B8=80=E8=BF=94=E5=9B=9E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
lab-27/lab-27-webflux-02/pom.xml | 32 ++++++
.../lab27/springwebflux/Application.java | 29 +++++
.../controller/UserController.java | 94 ++++++++++++++++
.../springwebflux/controller/UserRouter.java | 67 ++++++++++++
.../springwebflux/core/package-info.java | 4 +
.../springwebflux/core/vo/CommonResult.java | 102 ++++++++++++++++++
.../core/web/GlobalExceptionHandler.java | 48 +++++++++
.../core/web/GlobalResponseBodyHandler.java | 79 ++++++++++++++
.../lab27/springwebflux/vo/UserVO.java | 35 ++++++
.../META-INF/lab-27-webflux-01.kotlin_module | Bin 0 -> 16 bytes
.../META-INF/lab-27-webflux-01.kotlin_module | Bin 0 -> 16 bytes
lab-27/pom.xml | 1 +
12 files changed, 491 insertions(+)
create mode 100644 lab-27/lab-27-webflux-02/pom.xml
create mode 100644 lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/Application.java
create mode 100644 lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/controller/UserController.java
create mode 100644 lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/controller/UserRouter.java
create mode 100644 lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/package-info.java
create mode 100644 lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/vo/CommonResult.java
create mode 100644 lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/web/GlobalExceptionHandler.java
create mode 100644 lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/web/GlobalResponseBodyHandler.java
create mode 100644 lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/vo/UserVO.java
create mode 100644 lab-27/lab-27-webflux-02/target/classes/META-INF/lab-27-webflux-01.kotlin_module
create mode 100644 lab-27/lab-27-webflux-02/target/test-classes/META-INF/lab-27-webflux-01.kotlin_module
diff --git a/lab-27/lab-27-webflux-02/pom.xml b/lab-27/lab-27-webflux-02/pom.xml
new file mode 100644
index 00000000..2e83aa64
--- /dev/null
+++ b/lab-27/lab-27-webflux-02/pom.xml
@@ -0,0 +1,32 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.1.RELEASE
+
+
+ 4.0.0
+
+ lab-27-webflux-02
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+ 2.2.1.RELEASE
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
diff --git a/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/Application.java b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/Application.java
new file mode 100644
index 00000000..83e4bb31
--- /dev/null
+++ b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/Application.java
@@ -0,0 +1,29 @@
+package cn.iocoder.springboot.lab27.springwebflux;
+
+import cn.iocoder.springboot.lab27.springwebflux.core.web.GlobalResponseBodyHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.codec.ServerCodecConfigurer;
+import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
+
+@SpringBootApplication
+public class Application {
+
+ @Autowired
+ ServerCodecConfigurer serverCodecConfigurer;
+ @Autowired
+ RequestedContentTypeResolver requestedContentTypeResolver;
+
+ @Bean
+ public GlobalResponseBodyHandler responseWrapper() {
+ return new GlobalResponseBodyHandler(serverCodecConfigurer
+ .getWriters(), requestedContentTypeResolver);
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/controller/UserController.java b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/controller/UserController.java
new file mode 100644
index 00000000..9183d16d
--- /dev/null
+++ b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/controller/UserController.java
@@ -0,0 +1,94 @@
+package cn.iocoder.springboot.lab27.springwebflux.controller;
+
+import cn.iocoder.springboot.lab27.springwebflux.core.vo.CommonResult;
+import cn.iocoder.springboot.lab27.springwebflux.vo.UserVO;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 用户 Controller
+ */
+@RestController
+@RequestMapping("/users")
+public class UserController {
+
+ /**
+ * 查询用户列表
+ *
+ * @return 用户列表
+ */
+ @GetMapping("/list")
+ public Flux list() {
+ // 查询列表
+ List result = new ArrayList<>();
+ result.add(new UserVO().setId(1).setUsername("yudaoyuanma"));
+ result.add(new UserVO().setId(2).setUsername("woshiyutou"));
+ result.add(new UserVO().setId(3).setUsername("chifanshuijiao"));
+ // 返回列表
+ return Flux.fromIterable(result);
+ }
+
+ /**
+ * 获得指定用户编号的用户
+ *
+ * @param id 用户编号
+ * @return 用户
+ */
+ @GetMapping("/get")
+ public Mono get(@RequestParam("id") Integer id) {
+ // 查询用户
+ UserVO user = new UserVO().setId(id).setUsername("username:" + id);
+ // 返回
+ return Mono.just(user);
+ }
+
+ /**
+ * 获得指定用户编号的用户
+ *
+ * @param id 用户编号
+ * @return 用户
+ */
+ @GetMapping("/get2")
+ public Mono> get2(@RequestParam("id") Integer id) {
+ // 查询用户
+ UserVO user = new UserVO().setId(id).setUsername("username:" + id);
+ // 返回
+ return Mono.just(CommonResult.success(user));
+ }
+
+ /**
+ * 获得指定用户编号的用户
+ *
+ * @param id 用户编号
+ * @return 用户
+ */
+ @GetMapping("/get3")
+ public UserVO get3(@RequestParam("id") Integer id) {
+ // 查询用户
+ UserVO user = new UserVO().setId(id).setUsername("username:" + id);
+ // 返回
+ return user;
+ }
+
+ /**
+ * 获得指定用户编号的用户
+ *
+ * @param id 用户编号
+ * @return 用户
+ */
+ @GetMapping("/get4")
+ public CommonResult get4(@RequestParam("id") Integer id) {
+ // 查询用户
+ UserVO user = new UserVO().setId(id).setUsername("username:" + id);
+ // 返回
+ return CommonResult.success(user);
+ }
+
+}
diff --git a/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/controller/UserRouter.java b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/controller/UserRouter.java
new file mode 100644
index 00000000..21fc4c77
--- /dev/null
+++ b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/controller/UserRouter.java
@@ -0,0 +1,67 @@
+package cn.iocoder.springboot.lab27.springwebflux.controller;
+
+import cn.iocoder.springboot.lab27.springwebflux.vo.UserVO;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.StringUtils;
+import org.springframework.web.reactive.function.server.*;
+import reactor.core.publisher.Mono;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import static org.springframework.web.reactive.function.server.RequestPredicates.*;
+import static org.springframework.web.reactive.function.server.RouterFunctions.*;
+import static org.springframework.web.reactive.function.server.ServerResponse.*;
+
+/**
+ * 用户 Router
+ */
+@Configuration
+public class UserRouter {
+
+ @Bean
+ public RouterFunction userListRouterFunction() {
+ return RouterFunctions.route(RequestPredicates.GET("/users2/list"),
+ new HandlerFunction() {
+
+ @Override
+ public Mono handle(ServerRequest request) {
+ // 查询列表
+ List result = new ArrayList<>();
+ result.add(new UserVO().setId(1).setUsername("yudaoyuanma"));
+ result.add(new UserVO().setId(2).setUsername("woshiyutou"));
+ result.add(new UserVO().setId(3).setUsername("chifanshuijiao"));
+ // 返回列表
+ return ServerResponse.ok().bodyValue(result);
+ }
+
+ });
+ }
+
+ @Bean
+ public RouterFunction userGetRouterFunction() {
+ return RouterFunctions.route(RequestPredicates.GET("/users2/get"),
+ new HandlerFunction() {
+
+ @Override
+ public Mono handle(ServerRequest request) {
+ // 获得编号
+ Integer id = request.queryParam("id")
+ .map(s -> StringUtils.isEmpty(s) ? null : Integer.valueOf(s)).get();
+ // 查询用户
+ UserVO user = new UserVO().setId(id).setUsername(UUID.randomUUID().toString());
+ // 返回列表
+ return ServerResponse.ok().bodyValue(user);
+ }
+
+ });
+ }
+
+ @Bean
+ public RouterFunction demoRouterFunction() {
+ return route(GET("/users2/demo"), request -> ok().bodyValue("demo"));
+ }
+
+}
diff --git a/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/package-info.java b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/package-info.java
new file mode 100644
index 00000000..2194aca0
--- /dev/null
+++ b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 提供核心封装
+ */
+package cn.iocoder.springboot.lab27.springwebflux.core;
diff --git a/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/vo/CommonResult.java b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/vo/CommonResult.java
new file mode 100644
index 00000000..e1929aa5
--- /dev/null
+++ b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/vo/CommonResult.java
@@ -0,0 +1,102 @@
+package cn.iocoder.springboot.lab27.springwebflux.core.vo;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.springframework.util.Assert;
+
+import java.io.Serializable;
+
+/**
+ * 通用返回结果
+ *
+ * @param 结果泛型
+ */
+public class CommonResult implements Serializable {
+
+ public static Integer CODE_SUCCESS = 0;
+
+ /**
+ * 错误码
+ */
+ private Integer code;
+ /**
+ * 错误提示
+ */
+ private String message;
+ /**
+ * 返回数据
+ */
+ private T data;
+
+ /**
+ * 将传入的 result 对象,转换成另外一个泛型结果的对象
+ *
+ * 因为 A 方法返回的 CommonResult 对象,不满足调用其的 B 方法的返回,所以需要进行转换。
+ *
+ * @param result 传入的 result 对象
+ * @param 返回的泛型
+ * @return 新的 CommonResult 对象
+ */
+ public static CommonResult error(CommonResult> result) {
+ return error(result.getCode(), result.getMessage());
+ }
+
+ public static CommonResult error(Integer code, String message) {
+ Assert.isTrue(!CODE_SUCCESS.equals(code), "code 必须是错误的!");
+ CommonResult result = new CommonResult<>();
+ result.code = code;
+ result.message = message;
+ return result;
+ }
+
+ public static CommonResult success(T data) {
+ CommonResult result = new CommonResult<>();
+ result.code = CODE_SUCCESS;
+ result.data = data;
+ result.message = "";
+ return result;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public void setCode(Integer code) {
+ this.code = code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public T getData() {
+ return data;
+ }
+
+ public void setData(T data) {
+ this.data = data;
+ }
+
+ @JsonIgnore
+ public boolean isSuccess() {
+ return CODE_SUCCESS.equals(code);
+ }
+
+ @JsonIgnore
+ public boolean isError() {
+ return !isSuccess();
+ }
+
+ @Override
+ public String toString() {
+ return "CommonResult{" +
+ "code=" + code +
+ ", message='" + message + '\'' +
+ ", data=" + data +
+ '}';
+ }
+
+}
diff --git a/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/web/GlobalExceptionHandler.java b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/web/GlobalExceptionHandler.java
new file mode 100644
index 00000000..4b5f34e3
--- /dev/null
+++ b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/web/GlobalExceptionHandler.java
@@ -0,0 +1,48 @@
+package cn.iocoder.springboot.lab27.springwebflux.core.web;
+
+import org.springframework.web.bind.annotation.ControllerAdvice;
+
+@ControllerAdvice(basePackages = "cn.iocoder.springboot.lab23.springmvc.controller")
+public class GlobalExceptionHandler {
+
+// private Logger logger = LoggerFactory.getLogger(getClass());
+//
+// /**
+// * 处理 ServiceException 异常
+// */
+// @ResponseBody
+// @ExceptionHandler(value = ServiceException.class)
+// public CommonResult serviceExceptionHandler(HttpServletRequest req, ServiceException ex) {
+// logger.debug("[serviceExceptionHandler]", ex);
+// // 包装 CommonResult 结果
+// return CommonResult.error(ex.getCode(), ex.getMessage());
+// }
+//
+// /**
+// * 处理 MissingServletRequestParameterException 异常
+// *
+// * SpringMVC 参数不正确
+// */
+// @ResponseBody
+// @ExceptionHandler(value = MissingServletRequestParameterException.class)
+// public CommonResult missingServletRequestParameterExceptionHandler(HttpServletRequest req, MissingServletRequestParameterException ex) {
+// logger.debug("[missingServletRequestParameterExceptionHandler]", ex);
+// // 包装 CommonResult 结果
+// return CommonResult.error(ServiceExceptionEnum.MISSING_REQUEST_PARAM_ERROR.getCode(),
+// ServiceExceptionEnum.MISSING_REQUEST_PARAM_ERROR.getMessage());
+// }
+//
+// /**
+// * 处理其它 Exception 异常
+// */
+// @ResponseBody
+// @ExceptionHandler(value = Exception.class)
+// public CommonResult exceptionHandler(HttpServletRequest req, Exception e) {
+// // 记录异常日志
+// logger.error("[exceptionHandler]", e);
+// // 返回 ERROR CommonResult
+// return CommonResult.error(ServiceExceptionEnum.SYS_ERROR.getCode(),
+// ServiceExceptionEnum.SYS_ERROR.getMessage());
+// }
+
+}
diff --git a/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/web/GlobalResponseBodyHandler.java b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/web/GlobalResponseBodyHandler.java
new file mode 100644
index 00000000..635812c9
--- /dev/null
+++ b/lab-27/lab-27-webflux-02/src/main/java/cn/iocoder/springboot/lab27/springwebflux/core/web/GlobalResponseBodyHandler.java
@@ -0,0 +1,79 @@
+package cn.iocoder.springboot.lab27.springwebflux.core.web;
+
+import cn.iocoder.springboot.lab27.springwebflux.core.vo.CommonResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.MethodParameter;
+import org.springframework.core.ReactiveAdapterRegistry;
+import org.springframework.http.codec.HttpMessageWriter;
+import org.springframework.web.reactive.HandlerResult;
+import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
+import org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+import java.util.function.Function;
+
+public class GlobalResponseBodyHandler extends ResponseBodyResultHandler {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(GlobalResponseBodyHandler.class);
+
+ private static MethodParameter METHOD_PARAMETER_MONO_COMMON_RESULT;
+
+ private static final CommonResult COMMON_RESULT_SUCCESS = CommonResult.success(null);
+
+ static {
+ try {
+ // 获得 METHOD_PARAMETER_MONO_COMMON_RESULT 。其中 -1 表示 `#methodForParams()` 方法的返回值
+ METHOD_PARAMETER_MONO_COMMON_RESULT = new MethodParameter(
+ GlobalResponseBodyHandler.class.getDeclaredMethod("methodForParams"), -1);
+ } catch (NoSuchMethodException e) {
+ LOGGER.error("[static][获取 METHOD_PARAMETER_MONO_COMMON_RESULT 时,找不都方法");
+ throw new RuntimeException(e);
+ }
+ }
+
+ public GlobalResponseBodyHandler(List> writers, RequestedContentTypeResolver resolver) {
+ super(writers, resolver);
+ }
+
+ public GlobalResponseBodyHandler(List> writers, RequestedContentTypeResolver resolver, ReactiveAdapterRegistry registry) {
+ super(writers, resolver, registry);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Mono handleResult(ServerWebExchange exchange, HandlerResult result) {
+ Object returnValue = result.getReturnValue();
+ Object body = null;
+ if (returnValue instanceof Mono) {
+ body = ((Mono