增加部分示例代码
This commit is contained in:
parent
02f59c18ae
commit
26acc62ae0
14
README.md
14
README.md
@ -5,6 +5,15 @@
|
|||||||
##### 通过静态方法创建 Flux
|
##### 通过静态方法创建 Flux
|
||||||
Reactor 中静态创建 Flux 的方法常见的包括 just()、range()、interval() 以及各种以 from- 为前缀的方法组等。因为 Flux 可以代表 0 个数据,所以也有一些专门用于创建空序列的工具方法。
|
Reactor 中静态创建 Flux 的方法常见的包括 just()、range()、interval() 以及各种以 from- 为前缀的方法组等。因为 Flux 可以代表 0 个数据,所以也有一些专门用于创建空序列的工具方法。
|
||||||
empty()、error() 和 never()这三个方法类创建一些特殊的数据序列。其中,如果你希望创建一个只包含结束消息的空序列,那么可以使用 empty() 方法。error() 方法可以创建一个只包含错误消息的序列。如果你不希望所创建的序列不发出任何类似的消息通知,也可以使用 never() 方法实现这一目标。当然,这几个方法都比较少用,通常只用于调试和测试。
|
empty()、error() 和 never()这三个方法类创建一些特殊的数据序列。其中,如果你希望创建一个只包含结束消息的空序列,那么可以使用 empty() 方法。error() 方法可以创建一个只包含错误消息的序列。如果你不希望所创建的序列不发出任何类似的消息通知,也可以使用 never() 方法实现这一目标。当然,这几个方法都比较少用,通常只用于调试和测试。
|
||||||
|
* just():可以指定序列中包含的全部元素。创建出来的 Flux 序列在发布这些元素之后会自动结束。
|
||||||
|
* fromArray(),fromIterable()和 fromStream():可以从一个数组、Iterable 对象或 Stream 对象中创建 Flux 对象。
|
||||||
|
* empty():创建一个不包含任何元素,只发布结束消息的序列。
|
||||||
|
* error(Throwable error):创建一个只包含错误消息的序列。
|
||||||
|
* never():创建一个不包含任何消息通知的序列。
|
||||||
|
* range(int start, int count):创建包含从 start 起始的 count 个数量的 Integer 对象的序列。
|
||||||
|
* interval(Duration period)和 interval(Duration delay, Duration period):创建一个包含了从 0 开始递增的 Long 对象的序列。其中包含的元素按照指定的间隔来发布。除了间隔时间之外,还可以指定起始元素发布之前的延迟时间。
|
||||||
|
* intervalMillis(long period)和 intervalMillis(long delay, long period):与 interval()方法的作用相同,只不过该方法通过毫秒数来指定时间间隔和延迟时间。
|
||||||
|
|
||||||
##### 通过动态方法创建 Flux
|
##### 通过动态方法创建 Flux
|
||||||
动态创建 Flux 所采用的就是以编程的方式创建数据序列,最常用的就是 generate() 方法和 create() 方法。
|
动态创建 Flux 所采用的就是以编程的方式创建数据序列,最常用的就是 generate() 方法和 create() 方法。
|
||||||
generate() 方法生成 Flux 序列依赖于 Reactor 所提供的 SynchronousSink 组件
|
generate() 方法生成 Flux 序列依赖于 Reactor 所提供的 SynchronousSink 组件
|
||||||
@ -23,6 +32,11 @@ FluxSink 除了 next()、complete() 和 error() 这三个核心方法外,还
|
|||||||
可认为它是 Flux 的一种特例,所以很多创建 Flux 的方法同样适用。针对静态创建 Mono 的场景,前面给出的 just()、empty()、error() 和 never() 等方法同样适用。除了这些方法之外,比较常用的还有 justOrEmpty() 等方法。
|
可认为它是 Flux 的一种特例,所以很多创建 Flux 的方法同样适用。针对静态创建 Mono 的场景,前面给出的 just()、empty()、error() 和 never() 等方法同样适用。除了这些方法之外,比较常用的还有 justOrEmpty() 等方法。
|
||||||
justOrEmpty() 方法会先判断所传入的对象中是否包含值,只有在传入对象不为空时,Mono 序列才生成对应的元素
|
justOrEmpty() 方法会先判断所传入的对象中是否包含值,只有在传入对象不为空时,Mono 序列才生成对应的元素
|
||||||
另一方面,如果要想动态创建 Mono,我们同样也可以通过 create() 方法并使用 MonoSink 组件
|
另一方面,如果要想动态创建 Mono,我们同样也可以通过 create() 方法并使用 MonoSink 组件
|
||||||
|
* just(),empty(),error()和 never()同Flux
|
||||||
|
* fromCallable()、fromCompletionStage()、fromFuture()、fromRunnable()和 fromSupplier():分别从 Callable、CompletionStage、CompletableFuture、Runnable 和 Supplier 中创建 Mono。
|
||||||
|
* delay(Duration duration)和 delayMillis(long duration):创建一个 Mono 序列,在指定的延迟时间之后,产生数字 0 作为唯一值。
|
||||||
|
* ignoreElements(Publisher<T> source):创建一个 Mono 序列,忽略作为源的 Publisher 中的所有元素,只产生结束消息。
|
||||||
|
* justOrEmpty(Optional<? extends T> data)和 justOrEmpty(T data):从一个 Optional 对象或可能为 null 的对象中创建 Mono。只有 Optional 对象中包含值或对象不为 null 时,Mono 序列才产生对应的元素。
|
||||||
#### 订阅响应式流
|
#### 订阅响应式流
|
||||||
可通过 subscribe() 添加相应的订阅逻辑。调用 subscribe() 方法时可指定需要处理的消息通知类型。
|
可通过 subscribe() 添加相应的订阅逻辑。调用 subscribe() 方法时可指定需要处理的消息通知类型。
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
package com.qiuguo.iot.admin.http.api.controller;
|
package com.qiuguo.iot.admin.http.api.controller;
|
||||||
|
|
||||||
|
import com.qiuguo.iot.admin.http.api.req.DemoReq;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import reactor.core.CoreSubscriber;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ -52,4 +53,28 @@ public class DemoController {
|
|||||||
return flux;
|
return flux;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/post")//请求数据示例:{"aaa":"bbb"}
|
||||||
|
public Mono<String> postDemo(@RequestBody Mono<Map<String, Object>> contextMono){
|
||||||
|
Mono<String> mono =contextMono.map(item->{
|
||||||
|
for (Object o:item.values()
|
||||||
|
) {
|
||||||
|
log.info("接受到的信息{}", o);
|
||||||
|
}
|
||||||
|
return "1234";//返回结果
|
||||||
|
});
|
||||||
|
|
||||||
|
return mono;
|
||||||
|
}
|
||||||
|
@PostMapping("/post/demo")//请求数据示例:{"name":"bbb","id":123}
|
||||||
|
public Mono<DemoReq> postTest(@RequestBody Mono<DemoReq> contextMono){
|
||||||
|
Mono<DemoReq> mono =contextMono.map(item->{
|
||||||
|
log.info("接收到的对象:{}", item);
|
||||||
|
item.setId(456l);
|
||||||
|
item.setName("gaibian");
|
||||||
|
return item;//返回结果
|
||||||
|
});
|
||||||
|
|
||||||
|
return mono;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.qiuguo.iot.admin.http.api.req;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DemoReq {
|
||||||
|
private String name;
|
||||||
|
private Long id;
|
||||||
|
}
|
||||||
@ -24,9 +24,14 @@ public class DemoDataService extends GenericReactiveCrudService<DemoDataEntity,
|
|||||||
private final ReactiveUserService userService;
|
private final ReactiveUserService userService;
|
||||||
private final ReactiveAuthenticationManager authenticationManager;
|
private final ReactiveAuthenticationManager authenticationManager;
|
||||||
public Mono<DemoDataEntity> findDemoDataDetail(Long id){
|
public Mono<DemoDataEntity> findDemoDataDetail(Long id){
|
||||||
ReactiveValueOperations<String, Objects> operations = reactiveRedisTemplate.opsForValue();
|
/*
|
||||||
Mono<Objects> obj = operations.get("key");
|
ReactiveValueOperations 是 String (或 value) 的操作视图,
|
||||||
return Mono.just(new DemoDataEntity());/*Mono.zip(userService.findById(id.toString()),
|
操作视图还有ReactiveHashOperations、ReactiveListOperations、ReactiveSetOperations 和 ReactiveZSetOperations
|
||||||
|
*/
|
||||||
|
ReactiveValueOperations<String, DemoDataEntity> operations = reactiveRedisTemplate.opsForValue();
|
||||||
|
Mono<DemoDataEntity> obj = operations.get("key");
|
||||||
|
return obj;
|
||||||
|
/*return Mono.just(new DemoDataEntity());/*Mono.zip(userService.findById(id.toString()),
|
||||||
this.findById(id.toString()).defaultIfEmpty(new DemoDataEntity()),
|
this.findById(id.toString()).defaultIfEmpty(new DemoDataEntity()),
|
||||||
authenticationManager.getByUserId(id.toString())
|
authenticationManager.getByUserId(id.toString())
|
||||||
.map(Authentication::getDimensions).defaultIfEmpty(Collections.emptyList()).map(
|
.map(Authentication::getDimensions).defaultIfEmpty(Collections.emptyList()).map(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
server:
|
server:
|
||||||
port: 8090
|
port: 8091
|
||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
# 环境配置
|
# 环境配置
|
||||||
|
|||||||
@ -32,15 +32,15 @@ public class BoxWebSocketHandler implements WebSocketHandler {
|
|||||||
/**
|
/**
|
||||||
* 所有websocket连接管理容器
|
* 所有websocket连接管理容器
|
||||||
**/
|
**/
|
||||||
CountDownLatch countDownLatch = new CountDownLatch(5);
|
//CountDownLatch countDownLatch = new CountDownLatch(5);
|
||||||
FluxBatchRunner<MsgProtocol.Msg> batchRunner = new FluxBatchRunner<>(20, data -> {
|
FluxBatchRunner<MsgProtocol.Msg> batchRunner = new FluxBatchRunner<>(20, data -> {
|
||||||
log.info("begin:: thread={} 大小:{}", Thread.currentThread().getName(), data.size());
|
log.info("begin:: thread={} 大小:{}", Thread.currentThread().getName(), data.size());
|
||||||
for (MsgProtocol.Msg msg:data
|
for (MsgProtocol.Msg msg:data
|
||||||
) {
|
) {
|
||||||
for (UserInfo info:group.values()
|
for (UserInfo info:group.values()
|
||||||
) {
|
) {
|
||||||
//info.sendData(info.getSession().textMessage(""));
|
info.sendData(info.getSession().textMessage(""));
|
||||||
info.sendData(msg);
|
//info.sendData(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//data.clear();
|
//data.clear();
|
||||||
@ -49,7 +49,7 @@ public class BoxWebSocketHandler implements WebSocketHandler {
|
|||||||
//countDownLatch.countDown();
|
//countDownLatch.countDown();
|
||||||
//System.out.printf("begin:: thread=%s; data=%s", Thread.currentThread().getName());
|
//System.out.printf("begin:: thread=%s; data=%s", Thread.currentThread().getName());
|
||||||
|
|
||||||
log.info("end:: thread={} 大小{}", Thread.currentThread().getName(), data.size());
|
//log.info("end:: thread={} 大小{}", Thread.currentThread().getName(), data.size());
|
||||||
//System.out.printf("end:: thread=%s; size=%s%n", Thread.currentThread().getName(), data.size());
|
//System.out.printf("end:: thread=%s; size=%s%n", Thread.currentThread().getName(), data.size());
|
||||||
});
|
});
|
||||||
@Override
|
@Override
|
||||||
@ -86,22 +86,12 @@ public class BoxWebSocketHandler implements WebSocketHandler {
|
|||||||
|
|
||||||
if(reqMsg.getCmdId().getNumber() == MsgProtocol.Msg.CmdId.SEND_STATUS_REQ_VALUE){
|
if(reqMsg.getCmdId().getNumber() == MsgProtocol.Msg.CmdId.SEND_STATUS_REQ_VALUE){
|
||||||
MsgProtocol.Msg reqMsg1 = reqMsg.toBuilder().setCmdId(MsgProtocol.Msg.CmdId.SYNC_STATUS_RSP).build();
|
MsgProtocol.Msg reqMsg1 = reqMsg.toBuilder().setCmdId(MsgProtocol.Msg.CmdId.SYNC_STATUS_RSP).build();
|
||||||
for (UserInfo info:group.values()
|
/*for (UserInfo info:group.values()
|
||||||
) {
|
) {
|
||||||
//info.sendData(info.getSession().textMessage(""));
|
//info.sendData(info.getSession().textMessage(""));
|
||||||
info.sendData(reqMsg1);
|
info.sendData(reqMsg1);
|
||||||
}
|
|
||||||
//batchRunner.add(reqMsg1);
|
|
||||||
//IntStream.range(0, 100).forEach(batchRunner::add);
|
|
||||||
//group.values().forEach(batchRunner::add);
|
|
||||||
//batchRunner.doFinal();
|
|
||||||
/*try {
|
|
||||||
countDownLatch.await();
|
|
||||||
}catch (Exception e){
|
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
log.info("进来");
|
batchRunner.add(reqMsg1);
|
||||||
//group.forEach(batchRunner::add);
|
|
||||||
|
|
||||||
return Mono.empty();//session.textMessage("");
|
return Mono.empty();//session.textMessage("");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package com.qiuguo.iot.box.websocket.runner;
|
package com.qiuguo.iot.box.websocket.runner;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import reactor.core.publisher.MonoSink;
|
||||||
import reactor.core.scheduler.Scheduler;
|
import reactor.core.scheduler.Scheduler;
|
||||||
import reactor.core.scheduler.Schedulers;
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
|
||||||
@ -28,7 +30,11 @@ public class FluxBatchRunner<T> {
|
|||||||
Objects.requireNonNull(consumer);
|
Objects.requireNonNull(consumer);
|
||||||
this.batchSize = batchSize;
|
this.batchSize = batchSize;
|
||||||
this.consumer = consumer;
|
this.consumer = consumer;
|
||||||
scheduler = Schedulers.parallel();
|
//scheduler = Schedulers.parallel();//创建CPU内核数量一样多线程池;
|
||||||
|
//Schedulers.elastic() //无限制的弹性线程池,可以一直创建线程
|
||||||
|
//Schedulers.boundedElastic() //有界的弹性线程池,它会回收闲置的线程,默认是60s;它对创建的线程数做了限制,默认值为CPU内核数x 10,达到上限后,最多可提交10万个任务;
|
||||||
|
//Schedulers.fromExecutorService() 根据我们自定义线程池进行引用;
|
||||||
|
scheduler = Schedulers.single();//可重用单个线程
|
||||||
records = new ArrayList<>(batchSize);
|
records = new ArrayList<>(batchSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +76,11 @@ public class FluxBatchRunner<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void subscribeToMono(Collection<T> records) {
|
private void subscribeToMono(Collection<T> records) {
|
||||||
|
//subscribOn : 指定指定调度器,它会让整个事件处理流程进入切换线程处理;需要注意的是:不管怎么切换调度器,他都是单线程执行
|
||||||
Mono.just(records).subscribeOn(scheduler).subscribe(data -> consumer.accept(data));
|
Mono.just(records).subscribeOn(scheduler).subscribe(data -> consumer.accept(data));
|
||||||
|
|
||||||
|
//需要多线程执行必须使用parallel+runOn 如下
|
||||||
|
//Flux.just(records).parallel().runOn(scheduler).subscribe(data ->consumer.accept(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user