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));
}
}
- 访问
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