diff --git a/springboot-webflux-4-thymeleaf/pom.xml b/springboot-webflux-4-thymeleaf/pom.xml
new file mode 100755
index 0000000..2c437ce
--- /dev/null
+++ b/springboot-webflux-4-thymeleaf/pom.xml
@@ -0,0 +1,48 @@
+
+
+ 4.0.0
+
+ springboot
+ springboot-webflux-4-thymeleaf
+ 0.0.1-SNAPSHOT
+ springboot-webflux-4-thymeleaf :: Spring Boot WebFlux 整合 Thymeleaf
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.1.RELEASE
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ junit
+ junit
+ 4.12
+
+
+
+
diff --git a/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/Application.java b/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/Application.java
new file mode 100644
index 0000000..467400e
--- /dev/null
+++ b/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/Application.java
@@ -0,0 +1,19 @@
+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/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/dao/CityRepository.java b/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/dao/CityRepository.java
new file mode 100644
index 0000000..9ea9e9e
--- /dev/null
+++ b/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/dao/CityRepository.java
@@ -0,0 +1,43 @@
+package org.spring.springboot.dao;
+
+import org.spring.springboot.domain.City;
+import org.springframework.stereotype.Repository;
+
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+@Repository
+public class CityRepository {
+
+ private ConcurrentMap repository = new ConcurrentHashMap<>();
+
+ private static final AtomicLong idGenerator = new AtomicLong(0);
+
+ public Long save(City city) {
+ Long id = idGenerator.incrementAndGet();
+ city.setId(id);
+ repository.put(id, city);
+ return id;
+ }
+
+ public Collection findAll() {
+ return repository.values();
+ }
+
+
+ public City findCityById(Long id) {
+ return repository.get(id);
+ }
+
+ public Long updateCity(City city) {
+ repository.put(city.getId(), city);
+ return city.getId();
+ }
+
+ public Long deleteCity(Long id) {
+ repository.remove(id);
+ return id;
+ }
+}
diff --git a/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/domain/City.java b/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/domain/City.java
new file mode 100644
index 0000000..fa3b410
--- /dev/null
+++ b/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/domain/City.java
@@ -0,0 +1,60 @@
+package org.spring.springboot.domain;
+
+/**
+ * 城市实体类
+ *
+ */
+public class City {
+
+ /**
+ * 城市编号
+ */
+ private Long id;
+
+ /**
+ * 省份编号
+ */
+ private Long provinceId;
+
+ /**
+ * 城市名称
+ */
+ private String cityName;
+
+ /**
+ * 描述
+ */
+ private String description;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Long getProvinceId() {
+ return provinceId;
+ }
+
+ public void setProvinceId(Long provinceId) {
+ this.provinceId = provinceId;
+ }
+
+ public String getCityName() {
+ return cityName;
+ }
+
+ public void setCityName(String cityName) {
+ this.cityName = cityName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
diff --git a/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/handler/CityHandler.java b/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/handler/CityHandler.java
new file mode 100644
index 0000000..08e91f2
--- /dev/null
+++ b/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/handler/CityHandler.java
@@ -0,0 +1,39 @@
+package org.spring.springboot.handler;
+
+import org.spring.springboot.dao.CityRepository;
+import org.spring.springboot.domain.City;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+@Component
+public class CityHandler {
+
+ private final CityRepository cityRepository;
+
+ @Autowired
+ public CityHandler(CityRepository cityRepository) {
+ this.cityRepository = cityRepository;
+ }
+
+ public Mono save(City city) {
+ return Mono.create(cityMonoSink -> cityMonoSink.success(cityRepository.save(city)));
+ }
+
+ public Mono findCityById(Long id) {
+ return Mono.justOrEmpty(cityRepository.findCityById(id));
+ }
+
+ public Flux findAllCity() {
+ return Flux.fromIterable(cityRepository.findAll());
+ }
+
+ public Mono modifyCity(City city) {
+ return Mono.create(cityMonoSink -> cityMonoSink.success(cityRepository.updateCity(city)));
+ }
+
+ public Mono deleteCity(Long id) {
+ return Mono.create(cityMonoSink -> cityMonoSink.success(cityRepository.deleteCity(id)));
+ }
+}
diff --git a/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/webflux/controller/CityWebFluxController.java b/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/webflux/controller/CityWebFluxController.java
new file mode 100644
index 0000000..a0bb558
--- /dev/null
+++ b/springboot-webflux-4-thymeleaf/src/main/java/org/spring/springboot/webflux/controller/CityWebFluxController.java
@@ -0,0 +1,58 @@
+package org.spring.springboot.webflux.controller;
+
+import org.spring.springboot.domain.City;
+import org.spring.springboot.handler.CityHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.*;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+@Controller
+@RequestMapping(value = "/city")
+public class CityWebFluxController {
+
+ @Autowired
+ private CityHandler cityHandler;
+
+ @GetMapping(value = "/{id}")
+ @ResponseBody
+ public Mono findCityById(@PathVariable("id") Long id) {
+ return cityHandler.findCityById(id);
+ }
+
+ @GetMapping()
+ @ResponseBody
+ public Flux findAllCity() {
+ return cityHandler.findAllCity();
+ }
+
+ @PostMapping()
+ @ResponseBody
+ public Mono saveCity(@RequestBody City city) {
+ return cityHandler.save(city);
+ }
+
+ @PutMapping()
+ @ResponseBody
+ public Mono modifyCity(@RequestBody City city) {
+ return cityHandler.modifyCity(city);
+ }
+
+ @DeleteMapping(value = "/{id}")
+ @ResponseBody
+ public Mono deleteCity(@PathVariable("id") Long id) {
+ return cityHandler.deleteCity(id);
+ }
+
+ private static final String CITY_LIST_PATH_NAME = "cityList";
+
+ @GetMapping("/page/list")
+ public String listPage(final Model model) {
+ final Flux cityFluxList = cityHandler.findAllCity();
+ model.addAttribute("cityList", cityFluxList);
+ return CITY_LIST_PATH_NAME;
+ }
+
+}
diff --git a/springboot-webflux-4-thymeleaf/src/main/resources/application.properties b/springboot-webflux-4-thymeleaf/src/main/resources/application.properties
new file mode 100644
index 0000000..e69de29
diff --git a/springboot-webflux-4-thymeleaf/src/main/resources/templates/cityList.html b/springboot-webflux-4-thymeleaf/src/main/resources/templates/cityList.html
new file mode 100644
index 0000000..3245b7e
--- /dev/null
+++ b/springboot-webflux-4-thymeleaf/src/main/resources/templates/cityList.html
@@ -0,0 +1,38 @@
+
+
+
+
+ 城市列表
+
+
+
+
+
+
+
+
+
+
+
+ | 城市编号 |
+ 省份编号 |
+ 名称 |
+ 描述 |
+
+
+
+
+ |
+ |
+ |
+ |
+
+
+
+
+
+
+
+