介 绍
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();
完
原文来自:点融黑帮
声明:所有来源为“聚合数据”的内容信息,未经本网许可,不得转载!如对内容有异议或投诉,请与我们联系。邮箱:marketing@think-land.com
支持全球约2.4万个城市地区天气查询,如:天气实况、逐日天气预报、24小时历史天气等
支持识别各类商场、超市及药店的购物小票,包括店名、单号、总金额、消费时间、明细商品名称、单价、数量、金额等信息,可用于商品售卖信息统计、购物中心用户积分兑换及企业内部报销等场景
涉农贷款地址识别,支持对私和对公两种方式。输入地址的行政区划越完整,识别准确度越高。
根据给定的手机号、姓名、身份证、人像图片核验是否一致
通过企业关键词查询企业涉讼详情,如裁判文书、开庭公告、执行公告、失信公告、案件流程等等。