当RX遇上Spring——Spring 5新特性之响应式Web应用

Posted 点融黑帮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当RX遇上Spring——Spring 5新特性之响应式Web应用相关的知识,希望对你有一定的参考价值。


介 绍


1.1  何谓响应式编程?


简单来说,响应式编程讲的就是让应用变得异步、事件驱动,而且仅需少量线程就能在同一个JVM上垂直扩展而无需通过集群方式水平扩展。


响应式应用的一个关键特征就是背压。所谓背压就是一种保护消费者不被生产者的过度生产压垮的机制。举例来说,假如有一连串的从数据库一直延伸到HTTP响应的响应式组件,在HTTP链接太慢的情况下,数据仓储也会相应降低速度,或是在网络容量恢复前彻底停止工作。


响应式编程也使得编程范式从命令式向声明式的异步逻辑组合变迁。打个比方,命令式好比一个代码块来执行任务,声明式就是用Java 8的CompletableFuture通过lambda表达式来构建下一步的操作。


更全面的介绍参见Dave Syer的博客”Notes on Reactive Programming”。


1.2  响应式API与重要组建


Spring Framework 5用ReactiveStreams作为异步组件以及库之间的交流协议。Reactive Streams是业内协作共同构建的规格。Java 9也采用了Reactive Streams,并命名为java.util.concurrent.Flow。


Spring Framework内部采用Reactor来支持响应式编程。ReactiveStreams在实现Reactor时用Flux和Mono 这两个组合式API扩展了基本的Publisher协议,分别提供了对0..N以及0..1的数据序列的声明式操作的支持。


Spring框架在滋生的许多响应式API中同样暴露了Flux和Mono接口。在应用层,用户也可以选择使用Spring提供的对RxJava的全面支持。


更多响应式类型参见Sebastien Deleuze的”understanding Reactive Types”。



Spring Web响应式模块



Spring Framework 5包括了全新的spring-web-reactive模块。该模块提供了响应式HTTP以及WebSocket客户端的支持。在响应式Web应用服务器上也支持REST,html浏览器以及WebSocket类型的交互。


2.1  服务器端


服务器端支持两种不同的编程模型:


   基于注解(包括@Controller以及其他Spring MVC支持的注解)

   函数式(Java 8 lambda式的路由以及处理)


两种编程模型都是基于吧非阻塞HTTP运行时转化为Reactive Steams API。下图展示了服务器端技术栈。左边是传统的基于Servlet的Spring MVC(spring-web-mvc)以及右边的响应式技术栈(spring-web-reactive)。



全新的响应式技术栈能和运行在支持Servlet 3.1非阻塞IO API的Servlet容器之上,也能运行在诸如Netty活Undertow的异步运行时之上。所有的运行时都被包装秤响应式的ServerHttpRequest以及ServerHttpResponse,请求和响应体被表示为有背压支持的Flux<DataBuffer>而不是InputStream和OutputStream。Flux<Object>不仅支持REST风格的JSON和XML序列化和反序列化,也支持HTML视图渲染以及Server-Sent Events。


基于注解的编程模型:


Spring MVC 中的@Controller编程模式在响应式模式下同样得到支持。主要区别就是其使用的底层框架协议。在响应式模式下,HandlerMapping和HandlerAdaper是非阻塞的,而且工作在ServerHttpRequest和ServerHttpResponse之上,而不是传统的HttpServletRequest和HttpServletResponse之上。


例如这个响应式控制器:

@RestController
publicclass PersonController {

        privatefinalPersonRepository repository;

        publicPersonController(PersonRepository repository) {
               this.repository= repository;
        }

        @PostMapping("/person")
        Mono<Void> create(@RequestBody Publisher<Person> personStream) {
               returnthis.repository.save(personStream).then();
        }

        @GetMapping("/person")
        Flux<Person> list() {
               returnthis.repository.findAll();
        }

        @GetMapping("/person/{id}")
        Mono<Person> findById(@PathVariable String id) {
               returnthis.repository.findOne(id);
        }
}


函数式模型:


函数式模型用Java 8 lambda风格的撸起以及请求响应。主要的API是函数式接口RouterFunction和HandlerFunction。他们是创建Web应用简单又强大的工具。


函数式请求响应参见下例:

PersonRepository repository = ...

RouterFunctions
    .route(GET("/person/{id}").and(accept(APPLICATION_JSON)), request -> {
        int personId = Integer.valueOf(request.pathVariable("id"));
        Mono<ServerResponse> notFound = ServerResponse.notFound().build();
        return repository.findOne(personId)
                .then(person -> ServerResponse.ok().body(Mono.just(person), Person.class))
                .otherwiseIfEmpty(notFound);
    })
    .andRoute(GET("/person").and(accept(APPLICATION_JSON)), request ->
            ServerResponse.ok().body(repository.findAll(), Person.class))
    .andRoute(POST("/person").and(contentType(APPLICATION_JSON)), request ->
            ServerResponse.ok().build(repository.save(request.bodyToMono(Person.class))));

更多详情参见M3 release blog post


2.2  客户端


Spring Framework 5提供了一个函数式、响应式的WebClient。WebClient是

RestTemplate的全面的非阻塞、响应式的替代解决方案。他爸网络输入输出暴露为ClientHttpRequest和ClientHttpResponse,请求体和响应体为Flux<DataBuffer>。响应与服务器端,json, xml, sse的序列化在WebClient上也都有响应支持。WebClient需要一个ClientHttpConnector实例来诸如特定的HTTP客户端。


下例使用了Reactor Nettty:

WebClient client = WebClient.create(new ReactorClientHttpConnector());

ClientRequest<Void> request = ClientRequest
        .GET("http://example.com/accounts/{id}", 1L)
        .accept(APPLICATION_JSON)
        .build();




 

当RX遇上Spring——Spring 5新特性之响应式Web应用



点击回顾往期精彩内容























以上是关于当RX遇上Spring——Spring 5新特性之响应式Web应用的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码最难问题:当Spring AOP遇上循环依赖

Spring 当 @PathVariable 遇上 . # /等特殊字符

Spring boot 2.0 新特性之动态 Banner

Spring5框架 笔记总结

spring 5 新特性

Spring 5 新特性:函数式Web框架