Spring-WebFlux簡介與使用
簡介
Spring WebFlux是Spring Framework 5.0中引入的新的反應式Web框架。 與Spring MVC不同,它不需要Servlet API,完全非同步和非阻塞, 並通過Reactor專案實現Reactive Streams規範。 並且可以在諸如Netty,Undertow和Servlet 3.1+容器的伺服器上執行。
Reactor中的Mono和Flux
Flux 和 Mono 是 Reactor 中的兩個基本概念。Flux 表示的是包含 0 到 N 個元素的非同步序列。 在該序列中可以包含三種不同型別的訊息通知:正常的包含元素的訊息、序列結束的訊息和序列出錯的訊息。 當訊息通知產生時,訂閱者中對應的方法 onNext(), onComplete()和 onError()會被呼叫。Mono 表示的是包含 0 或者 1 個元素的非同步序列。 該序列中同樣可以包含與 Flux 相同的三種類型的訊息通知。Flux 和 Mono 之間可以進行轉換。 對一個 Flux 序列進行計數操作,得到的結果是一個 Mono物件。把兩個 Mono 序列合併在一起,得到的是一個 Flux 物件。
瞭解更多
WebFlux的使用方式
如圖所示,WebFlux支援兩種程式設計方式
- 基於SpringMvc註解@Controller
- 基於Java8 lambda樣式路由和處理
使用WebFlux需要單獨引用它的依賴,我使用的springboot,依賴如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <!--reactor的測試依賴--> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency>
示例
基於SpringMvc註解
與使用SpringMvc不同的是使用SpringWebFlux同一使用Mono<>,Flux<>物件同意返回資料,如下
@RestController @RequestMapping("/api/user") public class WebFluxController { private Map<Long,User> map = new HashMap<Long,User>(10); @PostConstruct public void init(){ map.put(1L,new User(1,"admin","admin")); map.put(2L,new User(1,"admin2","admin2")); map.put(3L,new User(1,"admin3","admin3")); } @GetMapping("/getAll") public Flux<User> getAllUser(){ return Flux.fromIterable(map.entrySet().stream().map(Map.Entry::getValue) .collect(Collectors.toList())); } @GetMapping("/{id}") public Mono<User> getUserById(@PathVariable("id") Long id){ return Mono.just(map.get(id)); } @PostMapping("/save") public Mono<ResponseEntity<String>> save(@RequestBody User user){ map.put(user.getUid(),user); return Mono.just(new ResponseEntity<>("新增成功", HttpStatus.CREATED)); } }
具體實現程式碼可檢視springboot-webflux
基於功能
處理請求的類,實現具體的業務邏輯,介面 ServerRequest 表示的是一個 HTTP 請求體。通過ServerRequest 物件可獲取到請求的相關資訊,如請求路徑、查詢引數和請求內容等。方法 的返回值是一個 Mono物件。介面 ServerResponse 用來表示 HTTP 響應。ServerResponse 中包含了很多靜態方法來建立不同 HTTP 狀態碼的響應物件
@Component public class UserHandler { private IUserService userService; @Autowired public UserHandler(IUserService userService) { this.userService = userService; } public Mono<ServerResponse> getAllUser(ServerRequest serverRequest){ Flux<User> allUser = userService.getAllUser(); return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(allUser,User.class); } public Mono<ServerResponse> getUserById(ServerRequest serverRequest){ //獲取url上的id Long uid = Long.valueOf(serverRequest.pathVariable("id")); Mono<User> user = userService.getUserById(uid); return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(user,User.class); } public Mono<ServerResponse> saveUser(ServerRequest serverRequest){ Mono<User> user = serverRequest.bodyToMono(User.class); return ServerResponse.ok().build(userService.saveUser(user)); } }
為Handler類新增路由資訊,
@Configuration public class RoutingConfiguration { @Bean public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler){ return route(GET("/api/user").and(accept(MediaType.APPLICATION_JSON)),userHandler::getAllUser) .andRoute(GET("/api/user/{id}").and(accept(MediaType.APPLICATION_JSON)),userHandler::getUserById) .andRoute(POST("/api/save").and(accept(MediaType.APPLICATION_JSON)),userHandler::saveUser); } }
具體實現程式碼可檢視springboot-webflux-functional