簡(jiǎn)介
Spring WebFlux是Spring Framework 5.0中引入的新的反應(yīng)式Web框架。與Spring MVC不同兔跌,它不需要Servlet API,完全異步和非阻塞,并通過(guò)Reactor項(xiàng)目實(shí)現(xiàn)Reactive Streams規(guī)范贴届。并且可以在諸如Netty劲够,Undertow和Servlet 3.1+容器的服務(wù)器上運(yùn)行震桶。
Reactor中的Mono和Flux
Flux 和 Mono 是 Reactor 中的兩個(gè)基本概念。Flux 表示的是包含 0 到 N 個(gè)元素的異步序列征绎。
在該序列中可以包含三種不同類型的消息通知:正常的包含元素的消息蹲姐、序列結(jié)束的消息和序列出錯(cuò)的消息。
當(dāng)消息通知產(chǎn)生時(shí)人柿,訂閱者中對(duì)應(yīng)的方法 onNext(), onComplete()和 onError()會(huì)被調(diào)用柴墩。Mono 表示的是包含 0 或者 1 個(gè)元素的異步序列。
該序列中同樣可以包含與 Flux 相同的三種類型的消息通知凫岖。Flux 和 Mono 之間可以進(jìn)行轉(zhuǎn)換江咳。
對(duì)一個(gè) Flux 序列進(jìn)行計(jì)數(shù)操作,得到的結(jié)果是一個(gè) Mono<Long>對(duì)象哥放。把兩個(gè) Mono 序列合并在一起歼指,得到的是一個(gè) Flux 對(duì)象爹土。 了解更多
WebFlux的使用方式
如圖所示,WebFlux支持兩種編程方式
- 基于SpringMvc注解@Controller
- 基于Java8 lambda樣式路由和處理
使用WebFlux需要單獨(dú)引用它的依賴,我使用的springboot,依賴如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!--reactor的測(cè)試依賴-->
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
示例
-
基于SpringMvc注解
與使用SpringMvc不同的是使用SpringWebFlux同一使用Mono<>,Flux<>對(duì)象同意返回?cái)?shù)據(jù)踩身,如下
@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)); } }
具體實(shí)現(xiàn)代碼可查看springboot-webflux
-
基于功能
處理請(qǐng)求的類胀茵,實(shí)現(xiàn)具體的業(yè)務(wù)邏輯,接口 ServerRequest 表示的是一個(gè) HTTP 請(qǐng)求體挟阻。通過(guò)ServerRequest 對(duì)象可獲取到請(qǐng)求的相關(guān)信息宰掉,如請(qǐng)求路徑、查詢參數(shù)和請(qǐng)求內(nèi)容等赁濒。方法 的返回值是一個(gè) Mono<T extends ServerResponse>對(duì)象轨奄。接口 ServerResponse 用來(lái)表示 HTTP 響應(yīng)。ServerResponse 中包含了很多靜態(tài)方法來(lái)創(chuàng)建不同 HTTP 狀態(tài)碼的響應(yīng)對(duì)象
@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); } }
具體實(shí)現(xiàn)代碼可查看springboot-webflux-functional