Reactive Streams 是 JVM 中面向流的库标准和规范:
处理可能无限数量的元素Backpressure(背压):背压是一种常用策略,使得发布者拥有无限制的缓冲区存储元素,用于确保发布者发布元素太快时,不会去压制订阅者。
Reactive Streams(响应式流)Reactor 框架是 Spring Boot Webflux 响应库依赖,通过 Reactive Streams 并与其他响应库交互。提供了 两种响应式 API:Mono 和 Flux。一般是将 Publisher 作为输入,在框架内部转换成 Reactor 类型并处理逻辑,然后返回 Flux 或 Mono 作为输出。
适用性:
MVC 能满足场景的,就不需要更改为 WebFlux。
要注意容器的支持,可以看看下面内嵌容器的支持。
微服务体系结构,WebFlux 和 MVC 可以混合使用。尤其开发 IO 密集型服务的时候,选择 WebFlux 去实现。
编程模型:
Spring 5 web 模块包含了 Spring WebFlux 的 HTTP 抽象。类似 Servlet API , WebFlux 提供了 WebHandler API 去定义非阻塞 API 抽象接口。可以选择以下两种编程模型实现:
注解控制层。和 MVC 保持一致,WebFlux 也支持响应性 @RequestBody 注解。
功能性端点。基于 lambda 轻量级编程模型,用来路由和处理请求的小工具。和上面最大的区别就是,这种模型,全程控制了请求 - 响应的生命流程
以上的都是一些概念,下面开始webflux的hello world小demo:
一,创建webflux项目
适用IDEA创建一个spring boot项目,引入spring-boot-starter-webflux包,如下图:
pom.xml里面的配置如下:
4.0.0
com.jack
webflux1
0.0.1-SNAPSHOT
jar
webflux1
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter-webflux
org.springframework.boot
spring-boot-starter-test
test
io.projectreactor
reactor-test
test
org.springframework.boot
spring-boot-maven-plugin
spring-boot-starter-webflux 依赖,是我们核心需要学习 webflux 的包,里面默认包含了 spring-boot-starter-reactor-netty 、spring 5 webflux 包,也就是说默认是通过 netty 启动的。
reactor-test、spring-boot-starter-test 两个依赖搭配是用于单元测试。
spring-boot-maven-plugin 是 Spring Boot Maven 插件,可以运行、编译等调用。
创建成功以后,启动成功后的输出如下:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.1.RELEASE)
2018-04-21 22:25:25.294 INFO 16920 --- [ main] com.jack.webflux1.Webflux1Application : Starting Webflux1Application on wj with PID 16920 (E:\webworkspace\IdeaProjects\springcloud4\webflux1\target\classes started by Administrator in E:\webworkspace\IdeaProjects\springcloud4)
2018-04-21 22:25:25.299 INFO 16920 --- [ main] com.jack.webflux1.Webflux1Application : No active profile set, falling back to default profiles: default
2018-04-21 22:25:25.342 INFO 16920 --- [ main] onfigReactiveWebServerApplicationContext : Refreshing org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext@1198b989: startup date [Sat Apr 21 22:25:25 GMT+08:00 2018]; root of context hierarchy
2018-04-21 22:25:26.354 INFO 16920 --- [ main] o.s.w.r.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.reactive.resource.ResourceWebHandler]
2018-04-21 22:25:26.354 INFO 16920 --- [ main] o.s.w.r.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.reactive.resource.ResourceWebHandler]
2018-04-21 22:25:26.425 INFO 16920 --- [ main] o.s.w.r.r.m.a.ControllerMethodResolver : Looking for @ControllerAdvice: org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext@1198b989: startup date [Sat Apr 21 22:25:25 GMT+08:00 2018]; root of context hierarchy
2018-04-21 22:25:26.756 INFO 16920 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2018-04-21 22:25:27.272 INFO 16920 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext : Started HttpServer on /0:0:0:0:0:0:0:0:8080
2018-04-21 22:25:27.272 INFO 16920 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2018-04-21 22:25:27.275 INFO 16920 --- [ main] com.jack.webflux1.Webflux1Application : Started Webflux1Application in 2.324
看输出,可以看到,默认使用netty作为容器启动,默认端口为8080
二,代码编写
1,编写处理器类handler
package com.jack.webflux1.handler;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
/**
* create by jack 2018/4/21
*/
@Component
public class HelloWorldHandler {
/**
* ServerResponse 是对响应的封装,可以设置响应状态、响应头、响应正文。
* 比如 ok 代表的是 200 响应码、MediaType 枚举是代表这文本内容类型、返回的是 String 的对象。
这里用 Mono 作为返回对象,是因为返回包含了一个 ServerResponse 对象,而不是多个元素
* @param request
* @return
*/
public Mono helloWorld(ServerRequest request) {
return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
.body(BodyInserters.fromObject("Hello, World Flux!"));
}
}
2,编写router
2,编写router路由器
package com.jack.webflux1.router;
import com.jack.webflux1.handler.HelloWorldHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
/**
* create by jack 2018/4/21
* 配置路由
*/
@Configuration
public class HelloWorldRouter {
/**
* RouterFunctions 对请求路由处理类,即将请求路由到处理器,这里将一个 GET 请求 /helloWorld 路由到处理器
* cityHandler 的 helloCity 方法上。跟 Spring MVC 模式下的 HandleMapping 的作用类似。
RouterFunctions.route(RequestPredicate, HandlerFunction) 方法,
对应的入参是请求参数和处理函数,如果请求匹配,就调用对应的处理器函数。
* @param helloWorldHandler
* @return
*/
@Bean
public RouterFunction routeHelloWorld(HelloWorldHandler helloWorldHandler) {
return RouterFunctions
.route(RequestPredicates.GET("/helloWorld")
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
helloWorldHandler::helloWorld);
}
}
上面的代码就编写完成了,进行请求,返回Hello, World Flux!
三,测试
启动应用,使用postman进行测试,url为:http://localhost:8080/helloWorld
返回结果如下图:
源码地址:https://github.com/wj903829182/springcloud5/tree/master/webflux1
学习来源参考:http://gitbook.cn/gitchat/column/5acda6f6d7966c5ae1086f2b/topic/5acda9d9d7966c5ae1087053
欢迎加群:331227121,一起学习交流