SpringBoot

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

2019-05-14  本文已影响0人  强某某

Webflux

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

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

2、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)

注意点:

需要把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

上一篇下一篇

猜你喜欢

热点阅读