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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容