如何在Spring Webflux中从Mono对象中提取数据而不阻塞?

huangapple go评论121阅读模式
英文:

How to extract data from a Mono object in Spring Webflux without blocking?

问题

以下是您提供的内容的翻译部分:

发送 POST 请求到我的 Spring 应用程序,使用 Postman。请求具有类似以下结构的 JSON 主体:

  1. {
  2. "documents": [
  3. {
  4. "id": "1",
  5. "text": "Piece of text 1",
  6. "lang": "en"
  7. },
  8. {
  9. "id": "2",
  10. "text": "Piece of text 2",
  11. "lang": "en"
  12. }
  13. ],
  14. "domain": "hr",
  15. "text_key": "text"
  16. }

我已经设置了一个方法来处理这些 POST 请求,我需要能够从请求体中提取上述 JSON 数据,而不阻塞。我现在的方法大致如下:

  1. public void requestBody(ServerRequest request) {
  2. Mono<String> bodyData = request.bodyToMono(String.class);
  3. System.out.println("\nsubscribing to the Mono.....");
  4. bodyData.subscribeOn(Schedulers.newParallel("requestBody")).subscribe(value -> {
  5. log.debug(String.format("%n value consumed: %s", value));
  6. });
  7. }

但是,这什么也没有做。我尝试查看了 https://stackoverflow.com/questions/52870517/spring-reactive-get-body-jsonobject-using-serverrequesthttps://stackoverflow.com/questions/54531407/getting-string-body-from-spring-serverrequest/54531866 中的答案,但没有成功。请帮忙解决。


更新 #1

感谢 https://stackoverflow.com/users/1189885/chrylis-cautiouslyoptimistic

根据您的答案,这是我尝试的内容:

  1. request.bodyToMono(String.class).map(
  2. (String rqBody) -> {
  3. setRequestBody(rqBody);
  4. return ServerResponse.status(HttpStatus.CREATED).contentType(APPLICATION_JSON).body(rqBody, Object.class);
  5. }
  6. );

setRequestBody() 是将全局字符串变量设置为请求体。像这样:

  1. public void setRequestBody(String rqBody){
  2. System.out.println("\nset request body called with: " + rqBody);
  3. request_body = rqBody;
  4. }

然而,全局变量 request_body 仍然是空的。


更新 #2

根据您最新的评论,这是我尝试的内容:

  1. RedissonClient redisson = Redisson.create();
  2. RBucket<Object> bucket = redisson.getBucket("requestKey");
  3. request.bodyToMono(String.class).doOnNext(
  4. (String rqBody) -> {
  5. bucket.set(rqBody);
  6. }
  7. );

当我进入 Redis-cli 并尝试 get requestKey 时,它会返回 nil

英文:

I am sending a POST request to my Spring application using Postman. The request has a JSON body that looks something like this:

  1. {
  2. &quot;documents&quot;: [
  3. {
  4. &quot;id&quot;: &quot;1&quot;,
  5. &quot;text&quot;: &quot;Piece of text 1&quot;,
  6. &quot;lang&quot;: &quot;en&quot;
  7. },
  8. {
  9. &quot;id&quot;: &quot;2&quot;,
  10. &quot;text&quot;: &quot;Piece of text 2&quot;,
  11. &quot;lang&quot;: &quot;en&quot;
  12. }
  13. ],
  14. &quot;domain&quot;: &quot;hr&quot;,
  15. &quot;text_key&quot;: &quot;text&quot;
  16. }

I have a method set up to handle these POST requests and I need to be able to extract the above JSON data from the request body WITHOUT BLOCKING. The method I have now looks something like this:

  1. public void requestBody(ServerRequest request) {
  2. Mono&lt;String&gt; bodyData = request.bodyToMono(String.class);
  3. System.out.println(&quot;\nsubscribing to the Mono.....&quot;);
  4. bodyData.subscribeOn(Schedulers.newParallel(&quot;requestBody&quot;)).subscribe(value -&gt; {
  5. log.debug(String.format(&quot;%n value consumed: %s&quot; ,value));
  6. });
  7. }

However, this does nothing. I tried looking at the answers in https://stackoverflow.com/questions/52870517/spring-reactive-get-body-jsonobject-using-serverrequest
AND
https://stackoverflow.com/questions/54531407/getting-string-body-from-spring-serverrequest/54531866 but to no avail. Please help out.


Update #1

thanks https://stackoverflow.com/users/1189885/chrylis-cautiouslyoptimistic

According to your answer, this is what I'm trying:

  1. request.bodyToMono(String.class).map(
  2. (String rqBody) -&gt; {
  3. setRequestBody(rqBody);
  4. return ServerResponse.status(HttpStatus.CREATED).contentType(APPLICATION_JSON).body(rqBody, Object.class);
  5. }
  6. );

setRequestBody() is setting a global string variable to be the request body. Like this:

  1. public void setRequestBody (String rqBody){
  2. System.out.println(&quot;\nset request body called with: &quot; + rqBody);
  3. request_body=rqBody;
  4. }

However, the global request_body variable is still null.


Update #2

This is what I'm trying to do as per your latest comment:

  1. RedissonClient redisson = Redisson.create();
  2. RBucket&lt;Object&gt; bucket = redisson.getBucket(&quot;requestKey&quot;);
  3. request.bodyToMono(String.class).doOnNext(
  4. (String rqBody) -&gt; {
  5. bucket.set(rqBody);
  6. }
  7. );

When I go into Redis-cli and try to get requestKey, it gives me nil

答案1

得分: 3

不能 这样做;这正是响应式模型的完整含义。相反,通常应使用诸如 map(通过应用函数来修改值)或 doOnNext(执行某些操作但不返回结果)之类的操作。

如果使用类似于 Spring WebFlux 的响应式执行模型,你可以直接从控制器方法返回一个 Mono<Whatever>,Spring 会为你“提取”数据。

英文:

You can't; that's the entire meaning of the reactive model. Instead, you should usually use operations like map (to modify the value by applying a function) or doOnNext (to take some action but not return a result).

If using a reactive execution model, such as Spring WebFlux, you directly return a Mono&lt;Whatever&gt; from your controller method, and Spring takes care of "extracting" the data for you.

huangapple
  • 本文由 发表于 2020年10月14日 21:30:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/64354402.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定