美文网首页SpringBoot
SpringBoot(七、sse,响应式编程)

SpringBoot(七、sse,响应式编程)

作者: 强某某 | 来源:发表于2019-05-14 17:11 被阅读0次

    Webflux

    1、Spring WebFlux是Spring Framework 5.0中引入的新的反应式Web框架

    与Spring MVC不同,它不需要Servlet API,完全异步和非阻塞,并 通过Reactor项目实现Reactive Streams规范。

    2、Flux和Mono

    • 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模型,如以下示例所示:

    第一种:
    @RestController 
    @RequestMapping(“/ users”)
    public  class MyRestController {
        @GetMapping(“/ {user}”)
        public Mono <User> getUser( @PathVariable Long user){
        }
    
        @GetMapping(“/ {user} / customers”)
        public Flux <Customer> getUserCustomers( @PathVariable Long user){
        }
    
        @DeleteMapping(“/ {user}”)
        public Mono <User> deleteUser( @PathVariable Long user){
        }
    }
    
    第二种: 路由配置与请求的实际处理分开
    @Configuration
    public  class RoutingConfiguration {
        @Bean
        public RouterFunction <ServerResponse> monoRouterFunction(UserHandler userHandler){
            return route(GET( “/ {user}”).and(accept(APPLICATION_JSON)),userHandler :: getUser)
            .andRoute(GET(“/ {user} / customers”).and(accept(APPLICATION_JSON)),userHandler :: getUserCustomers)
            .andRoute(DELETE(“/ {user}”).and(accept(APPLICATION_JSON)),userHandler :: deleteUser);
        }
    
    }
    
    @Component
    public class UserHandler {
    
        public Mono <ServerResponse> getUser(ServerRequest请求){
                         // ...
        }
    
        public Mono <ServerResponse> getUserCustomers(ServerRequest request){
                         // ...
        }
    
        public Mono <ServerResponse> deleteUser(ServerRequest请求){
                         // ...
        }
    }
    

    4、Spring WebFlux应用程序不严格依赖于Servlet API,因此它们不能作为war文件部署,也不能使用src/main/webapp目录

    5、可以整合多个模板引擎

    除了REST Web服务外,您还可以使用Spring WebFlux提供动态HTML内容。Spring WebFlux支持各种模板技术,包括Thymeleaf,FreeMarker

    基本使用

    • 添加依赖

    替代spring-boot-starter-web

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    
    • 控制器
    @RestController
    @RequestMapping("/api/v1/user")
    public class UserController {
    
        @GetMapping("test")
        public Mono<String> test() {
            return Mono.just("Hello");
        }
    
        //返回单个
        @GetMapping("getuser")
        public Mono<User> getUser() {
            User user=new User();
            user.setAge(10);
            user.setName("zq");
    //        Mono.justOrEmpty() 该方法代表有就返回否则返回null,一般使用这个
            return Mono.just(user);
        }
    
    
        //返回多个
        @GetMapping("getuserhaha")
        public Flux<User> getUsersHa() {
            Map<Integer,User> obj=new HashMap<>();
            for (int a=0;a<10;a++) {
                User user=new User();
                user.setAge(a);
                user.setName("zq"+a);
                obj.put(a,user);
            }
            return Flux.fromIterable(obj.values());
        }
        
        //响应是返回,每隔1秒返回一个,直到全部返回完全,只是一次网络请求
        @GetMapping(value = "getusers",produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
        public Flux<User> getUsers() {
            Map<Integer,User> obj=new HashMap<>();
            for (int a=0;a<10;a++) {
                User user=new User();
                user.setAge(a);
                user.setName("zq"+a);
                obj.put(a,user);
            }
            return Flux.fromIterable(obj.values()).delayElements(Duration.ofSeconds(1));
        }
    }
    
    • 访问

    http://127.0.0.1:8080/api/v1/user/getusers

    WebClient(反应式客户端)

    用于请求webflux服务端返回的数据,但是不常用

    官网地址

    @Test
        public void testHttp() {
            Mono<String> body= WebClient.create().get().uri("http://127.0.0.1:8080/api/v1/user/getuser")
                    .accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(String.class);
            System.out.println(body.block());
        }
    

    SSE

    服务端主动推送:SSE (Server Send Event)

    • html5新标准,用来从服务端实时推送数据到浏览器端,
    • 直接建立在当前http连接上,本质上是保持一个http长连接,轻量协议
    • 简单的服务器数据推送的场景,使用服务器推送事件

    注意点:

    需要把response的类型 改为 text/event-stream,才是sse的类型

    控制器

    @RequestMapping("/sse")
    @RestController
    public class SSEController {
    
        @RequestMapping(value = "getdata",produces = "text/event-stream;charset=UTF-8")
        public String push() {
    //        try {
    //            Thread.sleep(1000);
    //        } catch (InterruptedException e) {
    //            e.printStackTrace();
    //        }
    
            return Math.random()+"\n\n";
        }
    }
    

    html文件

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        <div>Test</div>
        <div id="result"></div>
    </body>
    </html>
    <script>
        var source=new EventSource('sse/getdata');
        source.onmessage=function (event) {
            document.getElementById('result').innerText=event.data;
        }
    </script>
    

    说明:sse是建立连接不断开(长连接),然后客户端会自动请求,相比于长轮询效率更高;sse还有有断开重试的功能,简化版websocket

    相关文章

      网友评论

        本文标题:SpringBoot(七、sse,响应式编程)

        本文链接:https://www.haomeiwen.com/subject/qtdeaqtx.html