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

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

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

问题

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

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

{
    "documents": [
        {
            "id": "1",
            "text": "Piece of text 1",
            "lang": "en"
        },
        {
            "id": "2",
            "text": "Piece of text 2",
            "lang": "en"
        }
    ],
    "domain": "hr",
    "text_key": "text"
}

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

public void requestBody(ServerRequest request) {

    Mono<String> bodyData = request.bodyToMono(String.class);

    System.out.println("\nsubscribing to the Mono.....");

    bodyData.subscribeOn(Schedulers.newParallel("requestBody")).subscribe(value -> {
        log.debug(String.format("%n value consumed: %s", value));
    });

}

但是,这什么也没有做。我尝试查看了 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

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

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

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

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

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


更新 #2

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

RedissonClient redisson = Redisson.create();

RBucket<Object> bucket = redisson.getBucket("requestKey");

request.bodyToMono(String.class).doOnNext(
    (String rqBody) -> {
        bucket.set(rqBody);
    }
);

当我进入 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:

{
        &quot;documents&quot;: [
            {
                &quot;id&quot;: &quot;1&quot;,
                &quot;text&quot;: &quot;Piece of text 1&quot;,
                &quot;lang&quot;: &quot;en&quot;
            },
            {
                &quot;id&quot;: &quot;2&quot;,
                &quot;text&quot;: &quot;Piece of text 2&quot;,
                &quot;lang&quot;: &quot;en&quot;
            }
        ],
        &quot;domain&quot;: &quot;hr&quot;,
        &quot;text_key&quot;: &quot;text&quot;
    }

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:

public void requestBody(ServerRequest request) {


      Mono&lt;String&gt; bodyData = request.bodyToMono(String.class);

      System.out.println(&quot;\nsubscribing to the Mono.....&quot;);

      bodyData.subscribeOn(Schedulers.newParallel(&quot;requestBody&quot;)).subscribe(value -&gt; {
        log.debug(String.format(&quot;%n value consumed: %s&quot; ,value));
      });

}

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:

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


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


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

However, the global request_body variable is still null.


Update #2

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



    RedissonClient redisson = Redisson.create();

    RBucket&lt;Object&gt; bucket = redisson.getBucket(&quot;requestKey&quot;);

      request.bodyToMono(String.class).doOnNext(
        (String rqBody) -&gt; {
          bucket.set(rqBody);
        }
      );

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:

确定