07-Spring5 WebFlux响应式编程
SpringWebFlux介绍
简介
- SpringWebFlux是Spring5添加的新模块,用于Web开发,功能和SpringMvc类似的,WebFlux使用当前一种比较流行的响应式编程框架
- 使用传统的Web框架,比如SpringMvc,这些是基于Servlet容器, WebFlux是一种异步非阻塞的框架,异步非阻塞的框架在Servlet3.1以后才支持,核心是基于Reactor的相关API实现的
什么是异步非阻塞
- 异步和同步
- 非阻塞和阻塞
- 上面都是针对对象不一样
异步和同步针对调度者,调用者发送请求,如果等待对方回应之后才去做其他事情,就是同步,如果发送请求之后不等着对方回应就去做其他事情就是异步
阻塞和非阻塞针对被调度者,被调度者收到请求后,做完请求任务之后才给出反馈就是阻塞,收到请求之后马上给出反馈然后去做事情,就是非阻塞
WebFlux特点
- 非阻塞式: 在有限资源下,提高系统吞吐量和伸缩性,以Reactor为基础实现响应式编程
- 函数式编程: Spring5框架基于Java8, WebFlux使用Java8函数式编程方式实现路由请求
比较SpringMvc
- 第一: 两个框架都可以使用注解方式,都运行在Tomcat等容器中
- 第二: SpringMvc采用命令式编程, WebFlux采用异步响应式编程
响应式编程(Java实现)
什么是响应式编程
响应式编程是一种面向数据流和变化传播的编程范式,这意味着可以在编程语言中很方便的表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播,电子表格程序就是响应式编程的一个例子,单元格可以包含字面值或类似"=B1+C1"的公式,而包含公式的单元格的值会依据其他单元格的变化而变化.
Java8及其之前的版本
提供的 "观察者模式" 两个类Observer 和 Observable
新建SpringBoot项目
新建一个SpringBoot的项目,我直接建一个模块算了
ok了
编写代码
package com.dance.webflux.reactor8; import lombok.extern.slf4j.Slf4j; import java.util.Observable;
import java.util.Observer; @Slf4j
public class ObserverDemo extends Observable { public static void main(String[] args) { ObserverDemo observerDemo = new ObserverDemo(); // 添加观察者
observerDemo.addObserver((o, arg) -> {
log.info("o:{},arg:{}",o,arg);
System.out.println("发生变化");
}); // 添加观察者
observerDemo.addObserver((o, arg) -> {
log.info("o:{},arg:{}",o,arg);
System.out.println("手动被观察者通知,准备改变");
}); // 发生改变
observerDemo.setChanged(); // 通知观察者
observerDemo.notifyObservers(); } }
执行结果
23:00:10.650 [main] INFO com.dance.webflux.reactor8.ObserverDemo - o:com.dance.webflux.reactor8.ObserverDemo@504bae78,arg:null
手动被观察者通知,准备改变
23:00:10.663 [main] INFO com.dance.webflux.reactor8.ObserverDemo - o:com.dance.webflux.reactor8.ObserverDemo@504bae78,arg:null
发生变化
响应式编程(Reactor实现)
简介
- 响应式编程操作中,Reactor是满足Reactive规范框架
- Reactor有两个核心类, Mono和Flux,这两个类实现接口Publisher,提供丰富的操作符,Flux对象实现发布者,返回N个元素,Mono对象实现发布者,返回1或者0个元素
- Flux和Mono都是数据流的发布者,使用Flux和Mono都可以发出三种数据信号,"元素值","错误信号","完成信号",错误信号和完成信号都代表终止信号,终止信号用于告诉订阅者数据流结束了,错误信号终止数据流同时把错误信息传递给订阅者
代码演示Flux和Mono
引入依赖
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.1.5.RELEASE</version>
</dependency>
编写代码
package com.dance.webflux.reactor8; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class TestReactor { public static void main(String[] args) {
/*
* just 方法直接声明
*/
Flux flux = Flux.just(1, 2, 3); Mono mono = Mono.just(1); // 其他方法
// 数组
Integer[] array = new Integer[]{1,2,3,4};
Flux flux1 = Flux.fromArray(array);
// 集合
List array2 = Arrays.asList(1, 2, 3, 4);
Flux flux2 = Flux.fromIterable(array2);
// Stream
Stream stream = array2.stream();
Flux flux3 = Flux.fromStream(stream);
// 供给型函数式接口Stream
Flux tFlux = Flux.fromStream(() -> Stream.of(1, 2, 3)); } }
三种信号特点
- 错误信号和完成信号都是终止信号, 不能共存的
- 如果没有发送任何元素值,而是直接发送错误或者完成信号,表示是空数据流
- 如果没有错误信号,没有完成信号,表示是无限数据流
真的,去看一下Java8吧,不然真看不懂
订阅数据流
调用just或者其他方法只是声明数据流,数据流并没有发出,只有在进行订阅之后才会触发数据流,不订阅什么都不会发生
// 订阅数据流
flux.subscribe(x -> System.out.print(x + " "));
System.out.println();
mono.subscribe(System.out::println);
执行结果
1 2 3
1
操作符
对数据进行一道道操作,称为操作符,比如工厂流水线
第一: map 元素映射为新元素(来自StreamAPI)
第二 flatmap 元素映射为流
把每个元素转换为流 把转换之后多个流合并为一个流
SpringWebFlux执行流程和核心API
SpringWebFlux 基于Reactor,默认使用容器是Netty, Netty是高性能NIO框架,异步非阻塞的框架
Netty
BIO
执行过程
SpringWebFlux执行过程和SpringMvc相似
SpringWebFlux 核心控制器 DispatchHandler,实现接口WebHandler
接口WebHandler有一个接口
因为没有添加依赖所以IDEA中找不到(我找了好长时间)
添加WebFlux依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-webflux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
FAQ
如果添加依赖失败可以添加阿里云仓库
<repositories>
<repository>
<id>aliyun</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>aliyun-plugin</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
WebHandler
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
// package org.springframework.web.server; import reactor.core.publisher.Mono; public interface WebHandler {
Mono handle(ServerWebExchange exchange);
}
可以看出返回的就是Mono,一个或零个元素
DispatchHandler实现
@Override
public Mono handle(ServerWebExchange exchange) { // http请求
// 判断请求映射集合是否为空
if (this.handlerMappings == null) {
return createNotFoundError();
}
// 获取Request 判断是否存在前置处理
if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
return handlePreFlight(exchange);
}
/**
* 将映射集合转为Flux发布(Flux.fromIterable),通过映射集合中的映射获取匹配,
* 然后判断匹配完成后是否为空,为空返回没有找到(switchIfEmpty),然后流化执行handler处理器
* (invokeHandler),然后执行返回结果处理(handleResult) 返回一个或零个元素 Mono
* /
return Flux.fromIterable(this.handlerMappings)
.concatMap(mapping -> mapping.getHandler(exchange))
.next()
.switchIfEmpty(createNotFoundError())
.flatMap(handler -> invokeHandler(exchange, handler))
.flatMap(result -> handleResult(exchange, result));
}
组件介绍
DispatchHandler: 负责请求的处理
HandlerMapping: 请求映射处理
HandlerAdapter: 请求适配处理
HandlerResultHandler: 响应结果处理
函数式编程接口
SpringWebFlux 实现函数式编程,两个接口,RouteFunction(路由处理)和HandlerFunction(处理函数)
SpringWebFlux(基于注解编程模型)
- SpringWebFlux实现方式有两种: 注解编程模型和函数式编程模型
- 使用注解编程模型方式,和之前SpringMvc使用类似的,只需要把相关依赖配置到项目中,SpringBoot自动配置相关运行容器,默认情况下使用Netty服务器
创建SpringBoot项目,引入WebFlux-Starter
前面已经创建和引入了
配置文件修改
application.properties
server.port=8081
创建实体类
package com.dance.webflux.entity; import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; @Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private String sex;
private Integer age;
}
创建Service
新建UserService
package com.dance.webflux.service; import com.dance.webflux.entity.User;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; public interface UserService { /**
* 根据ID获取用户信息
* @param id id
* @return user
*/
Mono getUserById(int id); /**
* 获取全部用户信息
* @return 用户信息
*/
Flux getAllUser(); /**
* 保存用户信息
* @param user 用户信息
* @return void
*/
Mono saveUserInfo(Mono user); }
实现接口
package com.dance.webflux.service.impl; import com.dance.webflux.entity.User;
import com.dance.webflux.service.UserService;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import java.util.HashMap;
import java.util.Map; @Service
public class UserServiceImpl implements UserService { /**
* 创建 map 集合存储数据,模拟数据库
*/
private final Map<Integer,User> users = new HashMap<>();
{
this.users.put(1,new User("lucy","nan",20));
this.users.put(2,new User("mary","nv",30));
this.users.put(3,new User("jack","nv",50));
} @Override
public Mono getUserById(int id) {
// 返回一个或者0个元素
return Mono.justOrEmpty(users.get(id));
} @Override
public Flux getAllUser() {
// 返回多个元素,返回全部的值
return Flux.fromIterable(this.users.values());
} @Override
public Mono saveUserInfo(Mono user) {
// 处理数据后返回空
return user.doOnNext(x -> {
int key = users.size() + 1;
users.put(key,x);
}).thenEmpty(Mono.empty());
}
}
创建Controller
package com.dance.webflux.controller; import com.dance.webflux.entity.User;
import com.dance.webflux.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; @RestController
public class UserController { @Autowired
private UserService userService; @GetMapping("/getUserById/{id}")
public Mono getUserById(@PathVariable Integer id){
return userService.getUserById(id);
} @GetMapping("/getAllUser")
public Flux getAllUser(){
return userService.getAllUser();
} @PostMapping("/saveUserInfo")
public Mono saveUserInfo(@RequestBody User user){
return userService.saveUserInfo(Mono.just(user));
} }
启动项目
FAQ,我在启动的时候报错了,经过排查后是应为之前为了看类的使用引入的依赖的原因,导致JAR包冲突了
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
将这个JAR包注释掉后,重新启动就ok了
10:46:27.550 [Thread-1] DEBUG org.springframework.boot.devtools.restart.classloader.RestartClassLoader - Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@7d031891 . ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.1) 2021-12-13 10:46:27.952 INFO 21120 --- [ restartedMain] com.dance.webflux.WebfluxApplication : Starting WebfluxApplication using Java 1.8.0_162 on ZB-PF2P9QVH with PID 21120 (D:\zhangyugen@JD.com\coding\Spring5\webflux\target\classes started by ext.caiyuanqing in D:\zhangyugen@JD.com\coding\Spring5)
2021-12-13 10:46:27.954 INFO 21120 --- [ restartedMain] com.dance.webflux.WebfluxApplication : No active profile set, falling back to default profiles: default
2021-12-13 10:46:27.996 INFO 21120 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2021-12-13 10:46:27.996 INFO 21120 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2021-12-13 10:46:28.777 INFO 21120 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2021-12-13 10:46:29.151 INFO 21120 --- [ restartedMain] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port 8081
2021-12-13 10:46:29.158 INFO 21120 --- [ restartedMain] com.dance.webflux.WebfluxApplication : Started WebfluxApplication in 1.598 seconds (JVM running for 2.507)
测试接口
根据ID获取用户信息
http://localhost:8081/getUserById/1
查询所有用户
http://localhost:8081/getAllUser
说明
SpringMvc方式实现,同步阻塞的方式, 基于SpringMvc+Servlet+Tomcat
SpringWebFlux方式实现,异步非阻塞的方式,基于SpringWebFlux+Reactor+Netty
SpringWebFlux(基于函数式编程模型)
- 在使用函数式编程模型操作的时候,需要自己初始化服务器
- 基于函数式编程模型的时候,有两个核心接口,RouterFunction(实现路由功能, 请求转发给相应的Handler)和HandlerFunction(处理请求生成响应的函数),核心任务定义两个函数式接口的实现,并且启动需要的服务器
- SpringWebFlux请求和响应不再是ServletRequest和ServletResponse,而是ServerRequest和ServerResponse
创建Handler(具体实现方法)
package com.dance.webflux.handler; import com.dance.webflux.entity.User;
import com.dance.webflux.service.UserService;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; public class UserHandler { private final UserService userService; public UserHandler(UserService userService) {
this.userService = userService;
} /**
* 根据ID查询用户信息
* @param serverRequest 请求体
* @return 响应体
*/
public Mono getUserById(ServerRequest serverRequest){
int id = Integer.parseInt(serverRequest.pathVariable("id"));
Mono userById = userService.getUserById(id);
return userById.flatMap(user -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(user).switchIfEmpty(ServerResponse.notFound().build()));
} /**
* 查询所有用户
* @param serverRequest 请求体
* @return 响应体
*/
public Mono getUserAll(ServerRequest serverRequest){
Flux allUser = userService.getAllUser();
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(allUser,User.class);
} /**
* 保存用户信息
* @param serverRequest 请求体
* @return 响应体
*/
public Mono saveUserInfo(ServerRequest serverRequest){
Mono userMono = serverRequest.bodyToMono(User.class);
return ServerResponse.ok().build(userService.saveUserInfo(userMono));
}
}
创建服务器(路由和适配器)
package com.dance.webflux; import com.dance.webflux.handler.UserHandler;
import com.dance.webflux.service.impl.UserServiceImpl;
import org.springframework.boot.autoconfigure.rsocket.RSocketProperties;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.netty.DisposableServer;
import reactor.netty.http.server.HttpServer; import java.io.IOException; import static org.springframework.web.reactive.function.server.RequestPredicates.*;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; public class FunctionServer { /**
* 创建路由
* @return 路由函数
*/
public RouterFunction routingFunction(){
// 创建UserService
UserServiceImpl userService = new UserServiceImpl();
// 创建处理器
UserHandler userHandler = new UserHandler(userService);
// 设置路由
return RouterFunctions
.route(GET("/user/{id}").and(accept(MediaType.APPLICATION_JSON)), userHandler::getUserById)
.andRoute(GET("/users").and(accept(MediaType.APPLICATION_JSON)), userHandler::getUserAll)
.andRoute(POST("/saveUserInfo"), userHandler::saveUserInfo);
} /**
* 创建服务器完成适配
*/
public void createReactorServer(){
// 路由和Handler适配
RouterFunction serverResponseRouterFunction = routingFunction();
// 转换为HttpHandler
HttpHandler httpHandler = toHttpHandler(serverResponseRouterFunction);
// 转换为适配器
ReactorHttpHandlerAdapter reactorHttpHandlerAdapter = new ReactorHttpHandlerAdapter(httpHandler);
// 创建HttpServer 设置端口
HttpServer httpServer = HttpServer.create().port(8081);
// 指定处理适配器并绑定
DisposableServer disposableServer = httpServer.handle(reactorHttpHandlerAdapter).bindNow();
} /**
* 启动
* @param args 参数
*/
public static void main(String[] args) throws IOException {
FunctionServer server = new FunctionServer();
server.createReactorServer();
System.out.println("enter to exit");
System.in.read(); } }
启动项目
启动main方法
16:06:37.931 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework
16:06:38.773 [main] DEBUG org.springframework.web.server.adapter.HttpWebHandlerAdapter - enableLoggingRequestDetails='false': form data and headers will be masked to prevent unsafe logging of potentially sensitive data
16:06:38.854 [main] DEBUG io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework
16:06:38.877 [main] DEBUG io.netty.util.internal.PlatformDependent0 - -Dio.netty.noUnsafe: false
16:06:38.878 [main] DEBUG io.netty.util.internal.PlatformDependent0 - Java version: 8
16:06:38.883 [main] DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available
16:06:38.885 [main] DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available
16:06:38.887 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Buffer.address: available
16:06:38.888 [main] DEBUG io.netty.util.internal.PlatformDependent0 - direct buffer constructor: available
16:06:38.891 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Bits.unaligned: available, true
16:06:38.894 [main] DEBUG io.netty.util.internal.PlatformDependent0 - jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable prior to Java9
16:06:38.894 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.DirectByteBuffer.(long, int): available
16:06:38.895 [main] DEBUG io.netty.util.internal.PlatformDependent - sun.misc.Unsafe: available
16:06:38.896 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.tmpdir: C:\Users\EXT~1.CAI\AppData\Local\Temp (java.io.tmpdir)
16:06:38.896 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.bitMode: 64 (sun.arch.data.model)
16:06:38.897 [main] DEBUG io.netty.util.internal.PlatformDependent - Platform: Windows
16:06:38.900 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.maxDirectMemory: 3760193536 bytes
16:06:38.900 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.uninitializedArrayAllocationThreshold: -1
16:06:38.902 [main] DEBUG io.netty.util.internal.CleanerJava6 - java.nio.ByteBuffer.cleaner(): available
16:06:38.902 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noPreferDirect: false
16:06:39.003 [main] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.level: simple
16:06:39.003 [main] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.targetRecords: 4
16:06:39.115 [main] DEBUG reactor.netty.tcp.TcpResources - [http] resources will use the default LoopResources: DefaultLoopResources {prefix=reactor-http, daemon=true, selectCount=8, workerCount=8}
16:06:39.115 [main] DEBUG reactor.netty.tcp.TcpResources - [http] resources will use the default ConnectionProvider: reactor.netty.resources.DefaultPooledConnectionProvider@26275bef
16:06:39.118 [main] DEBUG reactor.netty.resources.DefaultLoopIOUring - Default io_uring support : false
16:06:39.744 [main] DEBUG reactor.netty.resources.DefaultLoopEpoll - Default Epoll support : false
16:06:39.746 [main] DEBUG reactor.netty.resources.DefaultLoopKQueue - Default KQueue support : false
16:06:39.768 [main] DEBUG io.netty.channel.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 16
16:06:39.819 [main] DEBUG io.netty.util.internal.InternalThreadLocalMap - -Dio.netty.threadLocalMap.stringBuilder.initialSize: 1024
16:06:39.819 [main] DEBUG io.netty.util.internal.InternalThreadLocalMap - -Dio.netty.threadLocalMap.stringBuilder.maxSize: 4096
16:06:39.836 [main] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false
16:06:39.836 [main] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512
16:06:39.869 [main] DEBUG io.netty.util.internal.PlatformDependent - org.jctools-core.MpscChunkedArrayQueue: available
16:06:39.961 [main] DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.processId: 18728 (auto-detected)
16:06:39.965 [main] DEBUG io.netty.util.NetUtil - -Djava.net.preferIPv4Stack: false
16:06:39.965 [main] DEBUG io.netty.util.NetUtil - -Djava.net.preferIPv6Addresses: false
16:06:40.496 [main] DEBUG io.netty.util.NetUtilInitializations - Loopback interface: lo (Software Loopback Interface 1, 127.0.0.1)
16:06:40.498 [main] DEBUG io.netty.util.NetUtil - Failed to get SOMAXCONN from sysctl and file \proc\sys\net\core\somaxconn. Default: 200
16:06:40.971 [main] DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.machineId: 00:50:56:ff:fe:c0:00:08 (auto-detected)
16:06:41.012 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numHeapArenas: 16
16:06:41.012 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numDirectArenas: 16
16:06:41.012 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.pageSize: 8192
16:06:41.012 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxOrder: 11
16:06:41.012 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.chunkSize: 16777216
16:06:41.013 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.smallCacheSize: 256
16:06:41.013 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.normalCacheSize: 64
16:06:41.013 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedBufferCapacity: 32768
16:06:41.013 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimInterval: 8192
16:06:41.013 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimIntervalMillis: 0
16:06:41.013 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.useCacheForAllThreads: true
16:06:41.013 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedByteBuffersPerChunk: 1023
16:06:41.028 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: pooled
16:06:41.028 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 0
16:06:41.028 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384
16:06:41.216 [reactor-http-nio-1] DEBUG reactor.netty.transport.ServerTransport - [40eb46d7, L:/0:0:0:0:0:0:0:0:62011] Bound new server
enter to exit
测试
根据ID获取用户信息
http://localhost:8081/user/1
获取全部用户信息
http://localhost:8081/users
SpringWebFlux(WebClient调用)
编写WebClient
package com.dance.webflux; import com.dance.webflux.entity.User;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux; public class FunctionClient { public static void main(String[] args) {
//调用服务器地址
WebClient webClient = WebClient.create("http://127.0.0.1:8081");
//根据 id 查询
String id = "1";
User userresult = webClient.get().uri("/user/{id}", id).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class).block();
System.out.println(userresult);
//查询所有
Flux results = webClient.get().uri("/users").accept(MediaType.APPLICATION_JSON).retrieve().bodyToFlux(User.class);
results.map(User::getName).buffer().doOnNext(System.out::println).blockFirst();
} }
执行结果
16:19:25.382 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework
16:19:25.440 [main] DEBUG io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework
16:19:25.446 [main] DEBUG io.netty.util.internal.PlatformDependent0 - -Dio.netty.noUnsafe: false
16:19:25.447 [main] DEBUG io.netty.util.internal.PlatformDependent0 - Java version: 8
16:19:25.449 [main] DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available
16:19:25.450 [main] DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available
16:19:25.451 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Buffer.address: available
16:19:25.452 [main] DEBUG io.netty.util.internal.PlatformDependent0 - direct buffer constructor: available
16:19:25.453 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Bits.unaligned: available, true
16:19:25.453 [main] DEBUG io.netty.util.internal.PlatformDependent0 - jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable prior to Java9
16:19:25.454 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.DirectByteBuffer.(long, int): available
16:19:25.454 [main] DEBUG io.netty.util.internal.PlatformDependent - sun.misc.Unsafe: available
16:19:25.454 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.tmpdir: C:\Users\EXT~1.CAI\AppData\Local\Temp (java.io.tmpdir)
16:19:25.455 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.bitMode: 64 (sun.arch.data.model)
16:19:25.455 [main] DEBUG io.netty.util.internal.PlatformDependent - Platform: Windows
16:19:25.457 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.maxDirectMemory: 3760193536 bytes
16:19:25.457 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.uninitializedArrayAllocationThreshold: -1
16:19:25.459 [main] DEBUG io.netty.util.internal.CleanerJava6 - java.nio.ByteBuffer.cleaner(): available
16:19:25.459 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noPreferDirect: false
16:19:25.517 [main] DEBUG reactor.netty.tcp.TcpResources - [http] resources will use the default LoopResources: DefaultLoopResources {prefix=reactor-http, daemon=true, selectCount=8, workerCount=8}
16:19:25.517 [main] DEBUG reactor.netty.tcp.TcpResources - [http] resources will use the default ConnectionProvider: reactor.netty.resources.DefaultPooledConnectionProvider@13fee20c
16:19:25.635 [main] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.level: simple
16:19:25.636 [main] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.targetRecords: 4
16:19:26.686 [main] DEBUG io.netty.util.NetUtil - -Djava.net.preferIPv4Stack: false
16:19:26.687 [main] DEBUG io.netty.util.NetUtil - -Djava.net.preferIPv6Addresses: false
16:19:27.099 [main] DEBUG io.netty.util.NetUtilInitializations - Loopback interface: lo (Software Loopback Interface 1, 127.0.0.1)
16:19:27.100 [main] DEBUG io.netty.util.NetUtil - Failed to get SOMAXCONN from sysctl and file \proc\sys\net\core\somaxconn. Default: 200
16:19:27.138 [main] DEBUG org.springframework.web.reactive.function.client.ExchangeFunctions - [32502377] HTTP GET http://127.0.0.1:8081/user/1
16:19:27.158 [main] DEBUG reactor.netty.resources.DefaultLoopIOUring - Default io_uring support : false
16:19:27.682 [main] DEBUG reactor.netty.resources.DefaultLoopEpoll - Default Epoll support : false
16:19:27.683 [main] DEBUG reactor.netty.resources.DefaultLoopKQueue - Default KQueue support : false
16:19:27.690 [main] DEBUG io.netty.channel.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 16
16:19:27.711 [main] DEBUG io.netty.util.internal.InternalThreadLocalMap - -Dio.netty.threadLocalMap.stringBuilder.initialSize: 1024
16:19:27.711 [main] DEBUG io.netty.util.internal.InternalThreadLocalMap - -Dio.netty.threadLocalMap.stringBuilder.maxSize: 4096
16:19:27.720 [main] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false
16:19:27.720 [main] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512
16:19:27.732 [main] DEBUG io.netty.util.internal.PlatformDependent - org.jctools-core.MpscChunkedArrayQueue: available
16:19:28.183 [main] DEBUG io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider - Default DNS servers: [/10.2.255.200:53, /172.31.36.36:53, /172.31.37.37:53] (sun.net.dns.ResolverConfiguration)
16:19:28.193 [main] DEBUG reactor.netty.resources.PooledConnectionProvider - Creating a new [http] client pool [PoolFactory{evictionInterval=PT0S, leasingStrategy=fifo, maxConnections=500, maxIdleTime=-1, maxLifeTime=-1, metricsEnabled=false, pendingAcquireMaxCount=1000, pendingAcquireTimeout=45000}] for [/127.0.0.1:8081]
16:19:28.260 [main] DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.processId: 25696 (auto-detected)
16:19:28.611 [main] DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.machineId: 00:50:56:ff:fe:c0:00:08 (auto-detected)
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numHeapArenas: 16
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numDirectArenas: 16
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.pageSize: 8192
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxOrder: 11
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.chunkSize: 16777216
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.smallCacheSize: 256
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.normalCacheSize: 64
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedBufferCapacity: 32768
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimInterval: 8192
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimIntervalMillis: 0
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.useCacheForAllThreads: true
16:19:28.640 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedByteBuffersPerChunk: 1023
16:19:28.651 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: pooled
16:19:28.652 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 0
16:19:28.652 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384
16:19:28.681 [reactor-http-nio-2] DEBUG reactor.netty.resources.PooledConnectionProvider - [da237854] Created a new pooled channel, now: 0 active connections, 0 inactive connections and 0 pending acquire requests.
16:19:28.753 [reactor-http-nio-2] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
16:19:28.753 [reactor-http-nio-2] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkBounds: true
16:19:28.754 [reactor-http-nio-2] DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@74ee324f
16:19:28.761 [reactor-http-nio-2] DEBUG reactor.netty.transport.TransportConfig - [da237854] Initialized pipeline DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpClientCodec), (reactor.left.httpDecompressor = io.netty.handler.codec.http.HttpContentDecompressor), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
16:19:28.786 [reactor-http-nio-2] DEBUG reactor.netty.transport.TransportConnector - [da237854] Connecting to [/127.0.0.1:8081].
16:19:28.792 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Registering pool release on close event for channel
16:19:28.792 [reactor-http-nio-2] DEBUG reactor.netty.resources.PooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Channel connected, now: 1 active connections, 0 inactive connections and 0 pending acquire requests.
16:19:28.793 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}, [connected])
16:19:28.806 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854-1, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [configured])
16:19:28.808 [reactor-http-nio-2] DEBUG reactor.netty.http.client.HttpClientConnect - [da237854-1, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Handler is being applied: {uri=http://127.0.0.1:8081/user/1, method=GET}
16:19:28.810 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854-1, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/user/1, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [request_prepared])
16:19:28.834 [reactor-http-nio-2] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096
16:19:28.834 [reactor-http-nio-2] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 2
16:19:28.834 [reactor-http-nio-2] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.linkCapacity: 16
16:19:28.834 [reactor-http-nio-2] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
16:19:28.834 [reactor-http-nio-2] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.delayedQueue.ratio: 8
16:19:28.852 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854-1, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/user/1, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [request_sent])
16:19:28.860 [reactor-http-nio-2] DEBUG io.netty.handler.codec.compression.Brotli - brotli4j not in the classpath; Brotli support will be unavailable.
16:19:28.863 [reactor-http-nio-2] DEBUG reactor.netty.http.client.HttpClientOperations - [da237854-1, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Received response (auto-read:false) : [Content-Type=application/json, content-length=36]
16:19:28.863 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854-1, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/user/1, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [response_received])
16:19:28.870 [reactor-http-nio-2] DEBUG org.springframework.web.reactive.function.client.ExchangeFunctions - [32502377] [da237854-1, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Response 200 OK
16:19:28.981 [reactor-http-nio-2] DEBUG reactor.netty.channel.FluxReceive - [da237854-1, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] FluxReceive{pending=0, cancelled=false, inboundDone=false, inboundError=null}: subscribing inbound receiver
16:19:28.989 [reactor-http-nio-2] DEBUG reactor.netty.http.client.HttpClientOperations - [da237854-1, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Received last HTTP packet
16:19:29.026 [reactor-http-nio-2] DEBUG org.springframework.http.codec.json.Jackson2JsonDecoder - [32502377] [da237854-1, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Decoded [User(name=lucy, sex=nan, age=20)]
User(name=lucy, sex=nan, age=20)
16:19:29.026 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/user/1, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [response_completed])
16:19:29.026 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/user/1, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [disconnecting])
16:19:29.026 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Releasing channel
16:19:29.030 [reactor-http-nio-2] DEBUG reactor.netty.resources.PooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Channel cleaned, now: 0 active connections, 1 inactive connections and 0 pending acquire requests.
16:19:29.030 [main] DEBUG org.springframework.web.reactive.function.client.ExchangeFunctions - [58ce9668] HTTP GET http://127.0.0.1:8081/users
16:19:29.032 [reactor-http-nio-2] DEBUG reactor.netty.resources.PooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Channel acquired, now: 1 active connections, 0 inactive connections and 0 pending acquire requests.
16:19:29.032 [reactor-http-nio-2] DEBUG reactor.netty.http.client.HttpClientConnect - [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Handler is being applied: {uri=http://127.0.0.1:8081/users, method=GET}
16:19:29.032 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/users, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [request_prepared])
16:19:29.033 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/users, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [request_sent])
16:19:29.037 [reactor-http-nio-2] DEBUG reactor.netty.http.client.HttpClientOperations - [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Received response (auto-read:false) : [transfer-encoding=chunked, Content-Type=application/json]
16:19:29.037 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/users, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [response_received])
16:19:29.038 [reactor-http-nio-2] DEBUG org.springframework.web.reactive.function.client.ExchangeFunctions - [58ce9668] [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Response 200 OK
16:19:29.058 [reactor-http-nio-2] DEBUG reactor.netty.channel.FluxReceive - [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] FluxReceive{pending=0, cancelled=false, inboundDone=false, inboundError=null}: subscribing inbound receiver
16:19:29.064 [reactor-http-nio-2] DEBUG org.springframework.http.codec.json.Jackson2JsonDecoder - [58ce9668] [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Decoded [User(name=lucy, sex=nan, age=20)]
16:19:29.064 [reactor-http-nio-2] DEBUG org.springframework.http.codec.json.Jackson2JsonDecoder - [58ce9668] [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Decoded [User(name=mary, sex=nv, age=30)]
16:19:29.065 [reactor-http-nio-2] DEBUG org.springframework.http.codec.json.Jackson2JsonDecoder - [58ce9668] [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Decoded [User(name=jack, sex=nv, age=50)]
16:19:29.065 [reactor-http-nio-2] DEBUG reactor.netty.http.client.HttpClientOperations - [da237854-2, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Received last HTTP packet
[lucy, mary, jack]
16:19:29.066 [reactor-http-nio-2] DEBUG org.springframework.web.reactive.function.client.ExchangeFunctions - [58ce9668] Cancel signal (to close connection)
16:19:29.066 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/users, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [response_completed])
16:19:29.066 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] onStateChange(GET{uri=/users, connection=PooledConnection{channel=[id: 0xda237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081]}}, [disconnecting])
16:19:29.066 [reactor-http-nio-2] DEBUG reactor.netty.resources.DefaultPooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Releasing channel
16:19:29.066 [reactor-http-nio-2] DEBUG reactor.netty.resources.PooledConnectionProvider - [da237854, L:/127.0.0.1:62998 - R:/127.0.0.1:8081] Channel cleaned, now: 0 active connections, 1 inactive connections and 0 pending acquire requests.
里面有很完整的调用链信息,完结撒花花
若有收获,就点个赞吧
作者:彼岸舞
时间:2021\12\13
内容关于:Java
本文属于作者原创,未经允许,禁止转发
07-Spring5 WebFlux响应式编程的更多相关文章
- springboot2 webflux 响应式编程学习路径
springboot2 已经发布,其中最亮眼的非webflux响应式编程莫属了!响应式的weblfux可以支持高吞吐量,意味着使用相同的资源可以处理更加多的请求,毫无疑问将会成为未来技术的趋势,是必学 ...
- [转]springboot2 webflux 响应式编程学习路径
原文链接 spring官方文档 springboot2 已经发布,其中最亮眼的非webflux响应式编程莫属了!响应式的weblfux可以支持高吞吐量,意味着使用相同的资源可以处理更加多的请求,毫无疑 ...
- SpringBoot 2.x (14):WebFlux响应式编程
响应式编程生活案例: 传统形式: 一群人去餐厅吃饭,顾客1找服务员点餐,服务员把订单交给后台厨师,然后服务员等待, 当后台厨师做好饭,交给服务员,经过服务员再交给顾客1,依此类推,该服务员再招待顾客2 ...
- SpringBoot使用WebFlux响应式编程操作数据库
这一篇文章介绍SpringBoot使用WebFlux响应式编程操作MongoDb数据库. 前言 在之前一篇简单介绍了WebFlux响应式编程的操作,我们在来看一下下图,可以看到,在目前的Spring ...
- Spring WebFlux 响应式编程学习笔记(一)
各位Javaer们,大家都在用SpringMVC吧?当我们不亦乐乎的用着SpringMVC框架的时候,Spring5.x又悄(da)无(zhang)声(qi)息(gu)的推出了Spring WebFl ...
- spring5响应式编程
1.Spring5新特性 2.响应式编程响应式编程:非阻塞应用程序,借助异步和事件驱动还有少量的线程垂直伸缩,而非横向伸缩(分布式集群)当Http连接缓慢的时候,从数据库到Http数据响应中也会 ...
- 【SpringBoot】SpringBoot2.0响应式编程
========================15.高级篇幅之SpringBoot2.0响应式编程 ================================ 1.SprinBoot2.x响应 ...
- (转)Spring Boot 2 (十):Spring Boot 中的响应式编程和 WebFlux 入门
http://www.ityouknow.com/springboot/2019/02/12/spring-boot-webflux.html Spring 5.0 中发布了重量级组件 Webflux ...
- Spring Boot 2 (十):Spring Boot 中的响应式编程和 WebFlux 入门
Spring 5.0 中发布了重量级组件 Webflux,拉起了响应式编程的规模使用序幕. WebFlux 使用的场景是异步非阻塞的,使用 Webflux 作为系统解决方案,在大多数场景下可以提高系统 ...
随机推荐
- 问题 G: 心急的C小加
题目描述 C小加有一些木棒,它们的长度和质量都已经知道,需要一个机器处理这些木棒,机器开启的时候需要耗费一个单位的时间,如果第i+1个木棒的重量和长度都大于等于第i个处理的木棒,那么将不会耗费时间,否 ...
- ES6基础知识(Promise 对象)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Django 小实例S1 简易学生选课管理系统 7 修改个人信息
Django 小实例S1 简易学生选课管理系统 第7节--修改个人信息 点击查看教程总目录 作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师. 用户模块除了注册登录之外,还 ...
- dart系列之:dart类中的泛型
目录 简介 为什么要用泛型 怎么使用泛型 类型擦除 泛型的继承 泛型方法 总结 简介 熟悉JAVA的朋友可能知道,JAVA在8中引入了泛型的概念.什么是泛型呢?泛型就是一种通用的类型格式,一般用在集合 ...
- scrapy的安装,scrapy创建项目
简要: scrapy的安装 # 1)pip install scrapy -i https://pypi.douban.com/simple(国内源) 一步到位 # 2) 报错1: building ...
- 单线程 Redis 为什么这么快,看看这篇就知道了
Redis 作为一种 KV 缓存服务器,有着极高的性能,相对于 Memcache,Redis 支持更多种数据类型,因此在业界应用广泛. 记得刚毕业那会参加面试,面试官会问我 Redis 为什么快,由于 ...
- <C#任务导引教程>练习五
//27,创建一个控制台应用程序,声明两个DateTime类型的变量dt,获取系统的当前日期时间,然后使用Format格式化进行规范using System;class Program{ sta ...
- 应用SpringAOP及Tlog工具完成日志链路追踪、收集、持久化
一.痛点 目前我司各系统的日志管理比较原始,使用logback打日志到log文件,虽然有服务管理平台,但记录的日志也仅仅是前置机调用后台系统的出入参,当遇到问题时查日志较为麻烦. 登录VPN-打开服务 ...
- 访问ajax请求后的结果
let getJPM = (function() { let result; let url ="xxx"; $.ajax({ type: "post", ur ...
- CF 585 E Present for Vitalik the Philatelist
CF 585 E Present for Vitalik the Philatelist 我们假设 $ f(x) $ 表示与 $ x $ 互质的数的个数,$ s(x) $ 为 gcd 为 $ x $ ...