diff --git a/2-x-spring-boot-webflux-handling-errors/pom.xml b/2-x-spring-boot-webflux-handling-errors/pom.xml
new file mode 100755
index 0000000..aadde20
--- /dev/null
+++ b/2-x-spring-boot-webflux-handling-errors/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+ springboot
+ 2-x-spring-boot-webflux-handling-errors
+ 0.0.1-SNAPSHOT
+ 2-x-spring-boot-webflux-handling-errors
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/Application.java b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/Application.java
new file mode 100644
index 0000000..347d452
--- /dev/null
+++ b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/Application.java
@@ -0,0 +1,20 @@
+package org.spring.springboot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Spring Boot 应用启动类
+ *
+ */
+// Spring Boot 应用的标识
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ // 程序启动入口
+ // 启动嵌入式的 Tomcat 并初始化 Spring 环境及其各 Spring 组件
+ SpringApplication.run(Application.class,args);
+
+ }
+}
diff --git a/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/error/GlobalErrorAttributes.java b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/error/GlobalErrorAttributes.java
new file mode 100644
index 0000000..c8f7158
--- /dev/null
+++ b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/error/GlobalErrorAttributes.java
@@ -0,0 +1,32 @@
+package org.spring.springboot.error;
+
+import org.springframework.boot.web.reactive.error.DefaultErrorAttributes;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.ServerRequest;
+
+import java.util.Map;
+
+@Component
+public class GlobalErrorAttributes extends DefaultErrorAttributes {
+
+ @Override
+ public Map getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
+ Map map = super.getErrorAttributes(request, includeStackTrace);
+
+ if (getError(request) instanceof GlobalException) {
+ GlobalException ex = (GlobalException) getError(request);
+ map.put("exception", ex.getClass().getSimpleName());
+ map.put("message", ex.getMessage());
+ map.put("status", ex.getStatus().value());
+ map.put("error", ex.getStatus().getReasonPhrase());
+
+ return map;
+ }
+
+ map.put("exception", "SystemException");
+ map.put("message", "System Error , Check logs!");
+ map.put("status", "500");
+ map.put("error", " System Error ");
+ return map;
+ }
+}
diff --git a/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/error/GlobalErrorWebExceptionHandler.java b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/error/GlobalErrorWebExceptionHandler.java
new file mode 100644
index 0000000..32e6864
--- /dev/null
+++ b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/error/GlobalErrorWebExceptionHandler.java
@@ -0,0 +1,47 @@
+package org.spring.springboot.error;
+
+import org.springframework.boot.autoconfigure.web.ResourceProperties;
+import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
+import org.springframework.boot.web.reactive.error.ErrorAttributes;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.codec.ServerCodecConfigurer;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+import java.util.Map;
+
+@Component
+@Order(-2)
+public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
+
+ public GlobalErrorWebExceptionHandler(GlobalErrorAttributes g, ApplicationContext applicationContext,
+ ServerCodecConfigurer serverCodecConfigurer) {
+ super(g, new ResourceProperties(), applicationContext);
+ super.setMessageWriters(serverCodecConfigurer.getWriters());
+ super.setMessageReaders(serverCodecConfigurer.getReaders());
+ }
+
+ @Override
+ protected RouterFunction getRoutingFunction(final ErrorAttributes errorAttributes) {
+ return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
+ }
+
+ private Mono renderErrorResponse(final ServerRequest request) {
+
+ final Map errorPropertiesMap = getErrorAttributes(request, false);
+
+ return ServerResponse.status(HttpStatus.BAD_REQUEST)
+ .contentType(MediaType.APPLICATION_JSON_UTF8)
+ .body(BodyInserters.fromObject(errorPropertiesMap));
+ }
+
+}
diff --git a/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/error/GlobalException.java b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/error/GlobalException.java
new file mode 100644
index 0000000..e5e300b
--- /dev/null
+++ b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/error/GlobalException.java
@@ -0,0 +1,15 @@
+package org.spring.springboot.error;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.server.ResponseStatusException;
+
+public class GlobalException extends ResponseStatusException {
+
+ public GlobalException(HttpStatus status, String message) {
+ super(status, message);
+ }
+
+ public GlobalException(HttpStatus status, String message, Throwable e) {
+ super(status, message, e);
+ }
+}
diff --git a/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/handler/CityHandler.java b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/handler/CityHandler.java
new file mode 100644
index 0000000..56d0297
--- /dev/null
+++ b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/handler/CityHandler.java
@@ -0,0 +1,27 @@
+package org.spring.springboot.handler;
+
+import org.spring.springboot.error.GlobalException;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+import java.util.Optional;
+
+@Component
+public class CityHandler {
+
+ public Mono helloCity(ServerRequest request) {
+ return ServerResponse.ok().body(sayHelloCity(request), String.class);
+ }
+
+ private Mono sayHelloCity(ServerRequest request) {
+ Optional cityParamOptional = request.queryParam("city");
+ if (!cityParamOptional.isPresent()) {
+ throw new GlobalException(HttpStatus.INTERNAL_SERVER_ERROR, "request param city is ERROR");
+ }
+
+ return Mono.just("Hello," + cityParamOptional.get());
+ }
+}
diff --git a/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/router/CityRouter.java b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/router/CityRouter.java
new file mode 100644
index 0000000..0cef9af
--- /dev/null
+++ b/2-x-spring-boot-webflux-handling-errors/src/main/java/org/spring/springboot/router/CityRouter.java
@@ -0,0 +1,20 @@
+package org.spring.springboot.router;
+
+import org.spring.springboot.handler.CityHandler;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+
+@Configuration
+public class CityRouter {
+
+ @Bean
+ public RouterFunction routeCity(CityHandler cityHandler) {
+ return RouterFunctions.route(RequestPredicates.GET("/hello").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), cityHandler::helloCity);
+ }
+
+}
diff --git a/2-x-spring-boot-webflux-handling-errors/src/main/resources/application.properties b/2-x-spring-boot-webflux-handling-errors/src/main/resources/application.properties
new file mode 100644
index 0000000..e69de29
diff --git a/pom.xml b/pom.xml
index 73acb51..6a43a0b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,6 +9,8 @@
pom
+
+ 2-x-spring-boot-webflux-handling-errors
chapter-1-spring-boot-quickstart