day7 spring Webflux (2)

Spring Webflux(2)

执行流程与核心Api

spring Webflux 基于 Reactor,默认容器为 Netty,Netty 是高性能的 NIO 框架,异步非阻塞框架。

  1. Netty

    • BIO:阻塞方式
    • NIO:非阻塞方式
  2. 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);		//返回请求结果
                  });
              }
          }
      
  3. Spring Webflux 里的 DispatchHandler,负责请求的处理

    • HandlerMapper:请求查询到处理的方法
    • HandlerAdapter:真正负责请求处理
    • HandlerResultHandler:响应结果的处理
  4. Spring Webflux 实现函数式编程,两个接口:

    • RouterFunction:路由功能,将请求发送给对应的 Handler
    • HandlerFunction:处理函数,具体要执行的处理方法。

Spring Webflux 实现

实现方式分为两种:注解编程模型,函数式编程模型

注解方式

注解方式的使用,与 SpringMVC 使用方法类似,只要吧相关依赖配置到项目中。springboot 自动配置相关运行容器,默认情况下使用 Netty 服务器。

  1. 创建 springboot 工程,引入webflux 相关依赖。(springboot 2.0+ 版本默认为 spring5)

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
        <version>2.5.1</version>
    </dependency>
    
  2. 创建配置文件

  3. 创建包和相关接口类

    // 关于 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());
        }
    }
    
  4. 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);
        }
    }
    
函数式
  1. 在使用函数式编程模型操作时,需要自己初始化服务器

  2. 基于函数式编程模型操作时,有两个核心接口:

    • RouteFunction:实现路由,将请求转发给对应的 handler
    • HandlerFunction:处理请求生成响应的函数

    核心任务是定义两个函数式接口的实现并启动需要的服务器。.

  3. Spring Webflux 请求和响应不再是 ServletRequest 和 ServletResponse,而是 ServerRequest 和 ServerResponse

构建步骤

  1. 把注解编程模型复制一份,并修改。(dao包和 service不变)

  2. 创建 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));
        }
    }
    
  3. 初始化服务器,编写 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);
        }
        
    }
    
  4. 创建服务器,完成适配

    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();
    }
    
  5. 最终执行

    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();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值