WebFlux03 SpringBoot WebFlux实现CRUD
1 准备
基于SpringBoot2.0搭建WebFlux项目,详情请参见三少另外一篇博文
2 工程结构
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.xiangxu</groupId> <artifactId>springboot-webflux-2-crud</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot-webflux-2-crud</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> </plugins> </build> </project>
2.1 创建实体类
package cn.xiangxu.springbootwebflux2crud.domain; import lombok.Data; /** * @author 王杨帅 * @create 2018-06-21 10:42 * @desc 城市实体类 **/ @Data public class City { /** * 城市编号 */ private Long id; /** * 省份编号 */ private Long provinceId; /** * 城市名称 */ private String cityName; /** * 描述 */ private String description; }
2.2 创建持久层类
技巧01:本博文利用一个 Map 容器来存储数据
package cn.xiangxu.springbootwebflux2crud.dao; import cn.xiangxu.springbootwebflux2crud.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; /** * @author 王杨帅 * @create 2018-06-21 10:54 * @desc 城市持久层 **/ @Repository public class CityRepository { private ConcurrentMap<Long, City> 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<City> 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; } }
2.3 创建服务层【处理器类】
技巧01:在 SpringBoot WebFlux 中返回的数据类型是 Mono 或者 Flux 类型
技巧02:依赖注入时使用的是构造器注入,目的是为了减少和spring的耦合
package cn.xiangxu.springbootwebflux2crud.handler; import cn.xiangxu.springbootwebflux2crud.dao.CityRepository; import cn.xiangxu.springbootwebflux2crud.domain.City; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** * @author 王杨帅 * @create 2018-06-21 11:08 * @desc 城市处理器类 **/ @Component public class CityHandler { private final CityRepository cityRepository; public CityHandler(CityRepository cityRepository) { this.cityRepository = cityRepository; } public Mono<Long> save(City city) { return Mono.create(cityMonoSink -> cityMonoSink.success(cityRepository.save(city))); } public Mono<City> findCityById(Long id) { return Mono.justOrEmpty(cityRepository.findCityById(id)); } public Flux<City> findAllCity() { return Flux.fromIterable(cityRepository.findAll()); } public Mono<Long> modifyCity(City city) { return Mono.create(cityMonoSink -> cityMonoSink.success(cityRepository.updateCity(city))); } public Mono<Long> deleteCity(Long id) { return Mono.create(cityMonoSink -> cityMonoSink.success(cityRepository.deleteCity(id))); } }
2.4 创建控制层
技巧01:和SpringMVC的套路一样
package cn.xiangxu.springbootwebflux2crud.controller; import cn.xiangxu.springbootwebflux2crud.domain.City; import cn.xiangxu.springbootwebflux2crud.handler.CityHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** * @author 王杨帅 * @create 2018-06-21 11:10 * @desc 城市控制类 **/ @RestController @RequestMapping(value = "/city") public class CityWebFluxController { @Autowired private CityHandler cityHandler; @GetMapping(value = "/{id}") public Mono<City> findCityById(@PathVariable("id") Long id) { return cityHandler.findCityById(id); } @GetMapping() public Flux<City> findAllCity() { return cityHandler.findAllCity(); } @PostMapping() public Mono<Long> saveCity(@RequestBody City city) { return cityHandler.save(city); } @PutMapping() public Mono<Long> modifyCity(@RequestBody City city) { return cityHandler.modifyCity(city); } @DeleteMapping(value = "/{id}") public Mono<Long> deleteCity(@PathVariable("id") Long id) { return cityHandler.deleteCity(id); } }
3 Mono
- Mono:实现发布者,并返回 0 或 1 个元素,即单对象。
4 Flux
- Flux:实现发布者,并返回 N 个元素,即 List 列表对象。