Spring Webflux(2)
执行流程与核心Api
spring Webflux 基于 Reactor,默认容器为 Netty,Netty 是高性能的 NIO 框架,异步非阻塞框架。
-
Netty
- BIO:阻塞方式
- NIO:非阻塞方式
-
SpringWebflux 执行过程与 SpringMVC 类似
-
Webflux 核心控制器 DispatchHandler,实现了一个接口 WebHandler
-
接口 WebHandler,有一个实现方法 handle
public interface WebHandler{ Mono<Void> handle(ServerWebExchange var1); }
DispatchHandler 实现 WebHandler
public Mono<Void> handle(ServerWebExchange exchange) { // 放请求响应信息 if (this.handlerMappings == null) { return this.createNotFoundError(); } else { return CorsUtils.isPreFlightRequest(exchange.getRequest()) ? this.handlePreFlight(exchange) : Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> { return mapping.getHandler(exchange); // 根据请求地址获取对应 mapping }).next().switchIfEmpty(this.createNotFoundError()).flatMap((handler) -> { return this.invokeHandler(exchange, handler); //调用具体的业务方法 }).flatMap((result) -> { return this.handleResult(exchange, result); //返回请求结果 }); } }
-
-
Spring Webflux 里的 DispatchHandler,负责请求的处理
- HandlerMapper:请求查询到处理的方法
- HandlerAdapter:真正负责请求处理
- HandlerResultHandler:响应结果的处理
-
Spring Webflux 实现函数式编程,两个接口:
- RouterFunction:路由功能,将请求发送给对应的 Handler
- HandlerFunction:处理函数,具体要执行的处理方法。
Spring Webflux 实现
实现方式分为两种:注解编程模型,函数式编程模型
注解方式
注解方式的使用,与 SpringMVC 使用方法类似,只要吧相关依赖配置到项目中。springboot 自动配置相关运行容器,默认情况下使用 Netty 服务器。
-
创建 springboot 工程,引入webflux 相关依赖。(springboot 2.0+ 版本默认为 spring5)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> <version>2.5.1</version> </dependency>
-
创建配置文件
-
创建包和相关接口类
// 关于 service 接口 public interface UserService{ // 根据用户id查看用户 Mono<User> getUserById(int id); // 查询所有用户 Flux<User> getAllUser(); // 添加新用户 Mono<Void> saveUserInfo(Mono<User> user); }
@Service public class UserServiceImpl implements UserService{ private final Map<Integer,User> users = new HashMap<>(); public UserServiceImpl(){ this.users.put(1,new User("lili","man",20)); } public Mono<User> getUserById(int id){ return Mono.justOrEmpty(this.user.get(id)); } public Flux<User> getAllUser(){ return Flux.fromIterable(this.users.values()); } public Mono<Void> saveUserInfo(Mono<User> userMono){ return userMono.doOnNext(person ->{ int id = users.size()+1; users.put(id,person); }).thenEmpty(Mono.empty()); } }
-
controller 类创建
@RestController public class UserController{ @Autowired private UserService userService; // id查询 @GetMapping("/user/{id}") public Mono<User> getUserId(@PathVariable int id){ return userService.getUserById(id); } // 查询所有 @GetMapping("/user") public Flux<User> getUsers(){ return UserService.getAllUser(); } // 添加 @PostMapping("/saveUser") public Mono<void> saveUser(@RequestBody User){ Mono<user> userMono = Mono.just(user); userService.saveUserInfo(userMono); } }
函数式
-
在使用函数式编程模型操作时,需要自己初始化服务器
-
基于函数式编程模型操作时,有两个核心接口:
- RouteFunction:实现路由,将请求转发给对应的 handler
- HandlerFunction:处理请求生成响应的函数
核心任务是定义两个函数式接口的实现并启动需要的服务器。.
-
Spring Webflux 请求和响应不再是 ServletRequest 和 ServletResponse,而是 ServerRequest 和 ServerResponse
构建步骤:
-
把注解编程模型复制一份,并修改。(dao包和 service不变)
-
创建 Handler (具体实现)
public class UserHandler{ private final UserService userService; public UserHandler(UserService userService){ this.userService = userService; } // 根据id查询 public Mono<ServerResponse> getUserById(ServerRequest req){ int userId = Integer.parseInt(req.pathVariable("id")); // 空值处理 Mono<ServerResponse> notFound = ServerResponse.notFound().build(); Mono<User> userMono = this.userService.getUserById(userId); // 把userMono 进行转换返回 // 使用 Reactor 操作符 flatMap return userMono.flatMap(person ->{ ServerResponse.ok() .contentType(mediaType.APPLICATION_JSON) .body(fromObject(person)) }).switchIfEmpty(notFound); } // 查询所有 public Mono<ServerResponse> getAllUsers(ServerRequest req){ Flux<User> users = this.userService.getAllUser(); return ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON) .body(users,User.class); } // 添加 public Mono<ServerResponse> saveUser(ServerRequest req){ Mono<User> userMono = req.bodyToMono(User.class); return ServerResponse .ok() .build(this.userService.saveUserInfo(userMono)); } }
-
初始化服务器,编写 Router
创建路由的方法:
public class Server{ //创建 Router 路由 public RouterFunction<ServerResponse> routingFunction(){ UserService userService = new UserServiceImpl(); UserHandler handler = new UserHandler(userService); RouterFunction .route(GET("/users/{id}").and(accept(APPLICATION_JSON)),handler::getUserById) .addRoute(GET("/users").and(accept(APPLICATION_JSON)),handler::getAllUsers); } }
-
创建服务器,完成适配
public void createReactorServer(){ // 路由和 handler 适配 RouterFunction<ServerResponse> route = routingFunction(); HttpHandler httHandler = toHttpHandler(route); ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler); //创建服务器 HttpServer httpServer = HttpServer.create(); httpServer.handle(adapter).bindNow(); }
-
最终执行
public static void main(String[] args) throws Exception{ Server server = new Server(); server.createReactorServer(); System.out.println("starting"); System.in.read(); }
使用 WebClient 调用
public static void main(String[] args){
// 调用服务器的地址
WebClient webClient = WebClient.create("http://127.0.0.1:5794");
// 根据id查询
String id = "1";
User userResult = webClient.get()
.uri("/users/{id}",id)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(User.class)
.block();
System.out.print(userResult.getName());
// 查询所有
Flux<User> results = webClient.get()
.uri("/users")
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToFlux(User.class);
results.map(stu -> stu.getName())
.buffer()
.doOnNext(System.out::println)
.blockFirst();
}