源无极

导航

 

 

 

 

一、SprinBoot2.x响应式编程简介


    简介:讲解什么是reactive响应式编程和使用的好处

    1、基础理解:
        依赖于事件,事件驱动(Event-driven)
        一系列事件称为“流”
        异步
        非阻塞

1)买奶茶的案例(一个一个等待处理)

2)响应式编程

        观察者模式:服务员一直观察后台的情况,然后通知客户

    网上的一个例子:
        int b= 2;
        int c=3
        int a = b+c  //命令式编程后续b和c变化,都不影响a
        b=5;

        int b= 2;
        int c= 3
        int a = b+c  //响应式编程中,a的变化,会和b、c的变化而变化(事件驱动)
        b=5;

    2、官网:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-webflux


        SpingBoot2底层是用spring5,开始支持响应式编程,Spring又是基于Reactor试下响应式。

    

    学习资料
        1、reactive-streams学习资料:http://www.reactive-streams.org/
        2、web-flux相关资料:https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#spring-webflux

 总结:响应式编程,必须每一个阶段都不阻塞,才能提升性能

 

二、SpringBoot2.x响应式编程webflux介绍


    简介:讲解SpringBoot2.x响应式编程介绍 Mono、Flux对象和优缺点
    
    1、Spring WebFlux是Spring Framework 5.0中引入的新的反应式Web框架
    与Spring MVC不同,它不需要Servlet API,完全异步和非阻塞,并 通过Reactor项目实现Reactive Streams规范。
    RxJava

 

    2、Flux和Mono  User List<User>
        1)简单业务而言:和其他普通对象差别不大,复杂请求业务,就可以提升性能
        2)通俗理解:
            Mono 表示的是包含 0 或者 1 个元素的异步序列 (序列理解成流)
                mono->单一对象 User     redis->用户ID-》唯一的用户Mono<User>  
            
            Flux 表示的是包含 0 到 N 个元素的异步序列
                flux->数组列表对象 List<User>   redis->男性用户->Flux<User>
            Flux 和 Mono 之间可以进行转换


    3、Spring WebFlux有两种风格:基于功能和基于注解的。基于注解非常接近Spring MVC模型,如以下示例所示:
        第一种:
          
        第二种:
         “WebFlux.fn”是功能变体,它将路由配置与请求的实际处理分开,如以下示例所示:

 1    @Configuration
 2 public class RoutingConfiguration {
 3 
 4     @Bean
 5     public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
 6         return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
 7                 .andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
 8                 .andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
 9     }
10 
11 }
12 
13 @Component
14 public class UserHandler {
15 
16     public Mono<ServerResponse> getUser(ServerRequest request) {
17         // ...
18     }
19 
20     public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
21         // ...
22     }
23 
24     public Mono<ServerResponse> deleteUser(ServerRequest request) {
25         // ...
26     }
27 }

 

 

    4、Spring WebFlux应用程序不严格依赖于Servlet API,因此它们不能作为war文件部署,也不能使用src/main/webapp目录
    
    5、可以整合多个模板引擎
        除了REST Web服务外,您还可以使用Spring WebFlux提供动态HTML内容。Spring WebFlux支持各种模板技术,包括Thymeleaf,FreeMarker

 

 

 
三、SpringBoot2.x webflux实战


    简介:webflux响应式编程实战
    
    1、WebFlux中,请求和响应不再是WebMVC中的ServletRequest和ServletResponse,而是ServerRequest和ServerResponse

    2、加入依赖,如果同时存在sprin g-boot-starter-web,则会优先用spring-boot-starter-web
      

 1  
 2 
 3     <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6     <groupId>com.itcast</groupId>
 7     <artifactId>Springboot08_A</artifactId>
 8     <version>0.0.1-SNAPSHOT</version>
 9     <parent>
10         <groupId>org.springframework.boot</groupId>
11         <artifactId>spring-boot-starter-parent</artifactId>
12         <version>2.0.1.RELEASE</version>
13     </parent>
14     <dependencies>
15         <!-- <dependency>
16             <groupId>org.springframework.boot</groupId>
17             <artifactId>spring-boot-starter-web</artifactId>
18         </dependency>     -->
19         <dependency>
20                 <groupId>org.springframework.boot</groupId>
21                 <artifactId>spring-boot-starter-webflux</artifactId>
22             </dependency>
23         <dependency>
24             <groupId>org.springframework.boot</groupId>
25             <artifactId>spring-boot-starter-test</artifactId>
26             <scope>test</scope>
27         </dependency>
28     
29     </dependencies>
30     <build>
31         <plugins>
32             <plugin>
33                 <groupId>org.springframework.boot</groupId>
34                 <artifactId>spring-boot-maven-plugin</artifactId>
35             </plugin>
36         </plugins>
37     </build>
38 
39 </project>

 

      官网说明

 测试

1)

2)


    

    3、启动方式默认是Netty,8080端口

    Netty:高性能网络框架,异步非阻塞

    4、参考:https://spring.io/blog/2016/04/19/understanding-reactive-types

   5.模拟数据库实现CRUD

   1)service

 1 package com.itcast.demo.service;
 2 
 3 import java.util.Collection;
 4 import java.util.HashMap;
 5 import java.util.Map;
 6 
 7 import org.springframework.stereotype.Service;
 8 
 9 import com.itcast.demo.domain.User;
10 
11 import reactor.core.publisher.Flux;
12 import reactor.core.publisher.Mono;
13 
14 @Service
15 public class UserService {
16 
17      //模拟数据库
18      private static final Map<String,User> map =new HashMap<>();
19       static{//一创建对象就初始化map
20           map.put("1", new User("1", "小王1"));
21           map.put("2", new User("2", "小王2"));
22           map.put("3", new User("3", "小王3"));
23           map.put("4", new User("4", "小王4"));
24           map.put("5", new User("5", "小王5"));
25           map.put("6", new User("6", "小王6"));
26           map.put("7", new User("7", "小王7"));
27           map.put("8", new User("8", "小王8"));          
28       }
29       //返回所有数据
30       public Flux<User> list(){
31           Collection<User> list = UserService.map.values();
32           return Flux.fromIterable(list);
33       }
34       //通过id查出
35       public Mono<User> getById(final String id){
36         return   Mono.justOrEmpty(UserService.map.get(id));
37       }
38       
39       //通过id删除用户
40       public Mono<User> del(final String id){
41         return  Mono.justOrEmpty(UserService.map.remove(id));
42       }
43 }

 

2)controller

 1 package com.itcast.demo.controller;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.beans.factory.annotation.Value;
 5 import org.springframework.web.bind.annotation.GetMapping;
 6 import org.springframework.web.bind.annotation.RequestMapping;
 7 import org.springframework.web.bind.annotation.RestController;
 8 
 9 import com.itcast.demo.domain.JsonData;
10 import com.itcast.demo.domain.User;
11 import com.itcast.demo.service.UserService;
12 
13 import reactor.core.publisher.Flux;
14 import reactor.core.publisher.Mono;
15 
16 /**
17  * @作者po
18  */
19 @RestController
20 @RequestMapping("/api/v1")
21 public class UserController {
22     //@Autowired
23     //private UserService userService;
24     
25     //通过构造的方式
26     private final UserService userService;
27     
28     public UserController(final UserService userService ) {
29         this.userService=userService;
30     }
31     @GetMapping("test")
32     public Mono<String> Test01() {
33         return Mono.just("hello Mono");
34     }
35     
36     @GetMapping("getById")
37     public Mono<User> getById(final String id){
38         return userService.getById(id);
39     }
40     @GetMapping("del")
41        public Mono<User> del(final String id){
42            return userService.del(id);
43        }
44     
45     @GetMapping("list")
46        public Flux<User> list(){
47            return userService.list();
48        }
49      
50 }

 

3)访问

4)list

5)del

6)调用list的时候,希望拿到一个值就返回,如何体现这种效果

1  //import org.springframework.http.MediaType;
2      //拿到一个值就返回,即2s就返回,produces不配就没有这样的效果
3     @GetMapping(value="list",produces=MediaType.APPLICATION_STREAM_JSON_VALUE)
4        public Flux<User> list(){//延迟两秒
5            return userService.list().delayElements(Duration.ofSeconds(2));
6        }

 

应该:服务端的推送(像流水一样)

 

四、WebFlux客户端WebClient讲解


    简介:讲解SpringBoot2.x WebFlux客户端WebClient的介绍和使用
        1、反应式客户端

        官网地址:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-webclient

实战

1)在测试

 1 package com.domain;
 2 
 3 import org.junit.Test;
 4 import org.springframework.http.MediaType;
 5 import org.springframework.web.reactive.function.client.WebClient;
 6 
 7 import reactor.core.publisher.Mono;
 8 
 9 public class WebClientTest {
10 
11     @Test
12       public void testBase(){
13         Mono<String> resp = WebClient.create()
14             .get()
15             //多个参数也可以直接放到map中,参数名与placeholder对应上即可
16             .uri("http://localhost:8080/api/v1/getById?id=1") //使用占位符
17             .accept(MediaType.APPLICATION_JSON)
18             .retrieve()
19             .bodyToMono(String.class);
20         System.out.println(resp.block());
21      
22       }
23     
24     @Test
25       public void testPlaceHolder(){
26         Mono<String> resp = WebClient.create()
27             .get()           
28             .uri("http://localhost:8080/api/v1/getById?id={id}",1) //使用占位符
29             .accept(MediaType.APPLICATION_JSON)
30             .retrieve()
31             .bodyToMono(String.class);
32         System.out.println(resp.block());
33      
34       }
35     
36 }

 

2)先启动主程序,再在方法上点JUnit Test

 

posted on 2018-11-29 22:32  源无极  阅读(462)  评论(0编辑  收藏  举报