大多数Spring Boot应用场景中,程序直接或间接的地使用SpringApplication API引导。其中又嵌入式Web容器对外提供HTTP服务。Web应用程序在在SpringBoot 1.x中有且仅有Servlet容器实现,包括传统的Servlet和Spring WebMVC。而从2.0版本开始新增了Reactive Web容器实现,即Spring 5.0 WebFlux。Spring Boot 2.0 在 SpringApplicationn API上新增了setWebApplicationType(WebApplicationType)方法。允许程序显示的设置Web应用的枚举。
WebFlux相对于Spring MVC的性能优势,网上已经有很多人做过测评了,本文就不再赘述。
下面我们来构建一个SpringBoot 2.0 WebFlux项目
1、pom依赖
<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>webflux1</artifactId> <version>0.0.1-SNAPSHOT</version> <name>webflux1</name> <description>Demo project for Spring Boot WebFlux</description> <properties> <swagger.version>3.0.0-SNAPSHOT</swagger.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-starter</artifactId> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.2.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.1.6.RELEASE</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.6</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
最重要的是引入webflux启动包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
2、准备User实体
package com.example.webflux1.domian; import lombok.Data; import lombok.ToString; @Data @ToString public class User { private long id; private String username; private String password; private String flag; }
3、创建UserService
package com.example.webflux1.service; import com.example.webflux1.domian.User; import com.example.webflux1.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @Service public class UserService { private final UserRepository userRepository; @Autowired public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public Mono<Long> save(User user){ Mono<Long> saveEnd = Mono.create(userMonoSink -> userMonoSink.success(userRepository.save(user))); return saveEnd; } public Mono<User> findUserById(long id){ Mono<User> user = Mono.justOrEmpty(userRepository.findUserById(id)); return user; } public Flux<User> findAllUser(){ Flux<User> userFlux = Flux.fromIterable(userRepository.findAll()); return userFlux; } public Mono<Long> deleteUserById(long id){ Mono<Long> objectMono = Mono.create(userMonoLink -> userMonoLink.success(userRepository.deleteUser(id))); return objectMono; } public Mono<Long> modifyCity(User user){ Mono<Long> objectMono = Mono.create(userMonoLink -> userMonoLink.success(userRepository.updateUser(user))); return objectMono; } }
4、创建UserRepository
package com.example.webflux1.repository; import com.example.webflux1.domian.User; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @Repository public class UserRepository { private ConcurrentHashMap<Long, User> concurrentHashMap = new ConcurrentHashMap<>(); private static final AtomicLong a = new AtomicLong(0); public Long save(User user) { long id = a.getAndIncrement(); user.setId(id); concurrentHashMap.put(id, user); System.out.println("concurrentHashMap: " + concurrentHashMap); return id; } public User findUserById(long id) { return concurrentHashMap.get(id); } public Long updateUser(User user) { long id = user.getId(); concurrentHashMap.put(id, user); System.out.println(concurrentHashMap.get(id)); return id; } public Long deleteUser(long id) { concurrentHashMap.remove(id); return id; } public ArrayList<User> findAll() { ArrayList<User> list = new ArrayList<>(); concurrentHashMap.forEach((key, value) -> list.add(value)); return list; } }
5、创建UserController
package com.example.webflux1.controller; import com.example.webflux1.domian.User; import com.example.webflux1.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @RestController public class UserController { @Autowired private UserService userService; @GetMapping("findUserById") public Mono<User> findUserById(@RequestParam long id){ return userService.findUserById(id); } @GetMapping("findAllUser") public Flux<User> findAllUser(){ Flux<User> allUser = userService.findAllUser(); System.out.println(allUser); return userService.findAllUser(); } @PostMapping("insertUser") public Mono<Long> saveUser(@RequestBody User user){ Mono<Long> save = userService.save(user); return save; } @PutMapping("modifyUser") public Mono<Long> modifyUser(@RequestBody User user){ Mono<Long> longMono = userService.modifyCity(user); return longMono; } @DeleteMapping("deleteUserById") public Mono<Long> deleteUserById(@RequestParam long id){ Mono<Long> longMono = userService.deleteUserById(id); return longMono; } }
6、启动类Webflux1Application
package com.example.webflux1; import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.reactive.config.EnableWebFlux; @EnableWebFlux @SpringBootApplication public class Webflux1Application { public static void main(String[] args) { SpringApplication.run(Webflux1Application.class, args); } }
由上面的例子可以看出,使用WebFlux时,Spring MVC的注解一样可以使用。启动界面干净利索。我们可以看到,springboot2的默认容器已经有tomcat变成了支持非阻塞的netty。
本期的例子就到这里了,下一节咱们简单聊一聊WebFlux的工作原理。