我在弹簧纸幅通量中使用纸幅反应性。我已经为POST请求实现了Handler函数。我希望服务器立即返回。因此,我实现了以下处理程序-:
public class Sample implements HandlerFunction<ServerResponse>{
public Mono<ServerResponse> handle(ServerRequest request) {
Mono bodyMono = request.bodyToMono(String.class);
bodyMono.map(str -> {
System.out.println("body got is " + str);
return str;
}).subscribe();
return ServerResponse.status(HttpStatus.CREATED).build();
}
}
但是map函数内部的print语句没有被调用。这意味着身体没有被抽出。 如果我没有立即返回响应并使用
return bodyMono.then(ServerResponse.status(HttpStatus.CREATED).build())
然后调用map函数。
那么,如何在后台对请求正文进行处理? 请帮忙。
编辑
我尝试使用flux.share(),如下所示:
Flux<String> bodyFlux = request.bodyToMono(String.class).flux().share();
Flux<String> processFlux = bodyFlux.map(str -> {
System.out.println("body got is");
try{
Thread.sleep(1000);
}catch (Exception ex){
}
return str;
});
processFlux.subscribeOn(Schedulers.elastic()).subscribe();
return bodyFlux.then(ServerResponse.status(HttpStatus.CREATED).build());
在上面的代码中,有时会调用map函数,有时不会。
答案 0 :(得分:0)
正如您所发现的,您不能随意subscribe()
bodyToMono()
返回的Mono,因为在这种情况下,主体根本不会传递给Mono
进行处理。 (您可以通过在该single()
中放置一个Mono
调用来进行验证,因为不会发出任何元素,它将引发异常。)
那么,如何在后台对我的请求正文进行处理?
如果您真的仍然想只是使用反应器在后台执行较长的任务,而立即返回,则可以执行以下操作:
return request.bodyToMono(String.class).doOnNext(str -> {
Mono.just(str).publishOn(Schedulers.elastic()).subscribe(s -> {
System.out.println("proc start!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("proc end!");
});
}).then(ServerResponse.status(HttpStatus.CREATED).build());
此方法立即将发出的元素发布到新的Mono
,并设置为在弹性调度程序上发布,然后在后台进行预订。但是,这很丑陋,也不是反应堆的设计目标。您可能在这里误解了反应堆/反应式编程背后的想法:
map()
方法不是为副作用而设计的,而是旨在将每个对象转换为另一个对象的。对于副作用,您需要doOnNext()
代替; map()
方法中的“其他处理”仍会阻塞该线程。如果您的应用程序不仅仅用于快速演示目的,并且/或者您需要大量使用此模式,那么我将认真考虑设置适当的工作队列。
答案 1 :(得分:0)
这不可能。
Web服务器(包括Reactor Netty,Tomcat等)在完成请求处理后会清理并回收资源。这意味着在完成控制器处理程序后,将回收或关闭HTTP资源,请求本身,可重用缓冲区等。此时,您无法再从请求正文中进行读取。
在您的情况下,您需要首先读取并缓冲整个请求正文,然后返回响应并启动一个任务,以在单独的执行中处理该请求。