如何验证/处理Spring WebClient的响应?

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

How to validate/process the Spring WebClient response?

问题

应用程序流程如下:

  1. Spring应用程序接收请求 -> {"id": "UUID"}
  2. 使用WebClient调用外部网络服务
  3. 验证从WebClient收到的第2步响应。如果验证通过,则返回true或false。
  4. 进行其他验证操作(通过调用其他进程或外部服务),然后将响应发送回用户。

这是我使用的WebClient(副本):

public Mono<Details> someRestCall(String name) {
    return this.webClient.get().uri("/{id}/details", name)
                    .retrieve().bodyToMono(Details.class);
}

现在,我不想直接通过控制器将此Mono对象返回给客户端(如Angular应用程序),因为这是一个中间步骤。我想对从WebClient收到的响应运行一些验证。

我尝试过使用.block()方法来检索函数,但根据响应式编程,这似乎是一种不好的做法(阻塞操作)。
另外,我无法理解如何使用.subscribe()方法来检索响应对象并在其上运行验证/检查,如果验证通过则返回True

简单来说,与其从我的模块/验证代码返回Mono对象,我想返回一个普通的布尔值/Java对象。

我对响应式编程不太熟悉,有人可以帮助我解决这个问题吗?

英文:

So the app flow is like:

  1. Spring app receives the request -> {"id": "UUID"}
  2. Calls the external web service using the WebClient
  3. Validate the response received in step 2 from WebClient. Return true or false if validation passes.
  4. Do other validations operations(via calling other processes or ext services) and send back the response to the user.

This is the webclient which I am using(replica):

public Mono&lt;Details&gt; someRestCall(String name) {
		return this.webClient.get().url(&quot;/{id}/details&quot;, name)
						.retrieve().bodyToMono(Details.class);
	}

Now I don't want to return this Mono object directly to the client(like the Angular app) via the controller, since this is an intermediary step. I want to run few validations on the response received from the WebClient.

I have tried the .block() method to retrieve the function but it seems to be a bad practice as per the reactive programming. (blocking op)
Also, I am unable to understand how to use the .subscribe() method to retrieve the response object and run validation/checks on it and return True if the validation passes.

In simple terms, instead of returning a Mono object from my module/validation code, I want to return a normal boolean value/Java object.

I am new to reactive programming, can anyone please help me get this resolved?

答案1

得分: 1

带着一点努力,您可以在WebClient调用返回的POJO上使用基于JSR-303注解的验证。这里是一个最简示例:

@Component
public class MyClass {

  final Validator validator;

  MyClass(Validator validator) {
    this.validator = validator;
  }

  <T> T validate(T obj) {

    Set<ConstraintViolation<T>> violations = this.validator.validate(obj);
    if (violations.size() > 0) {
      throw new ResponseStatusException(INTERNAL_SERVER_ERROR, violations.toString());
    }

    return obj;
  }

  public Mono<Details> someRestCall(String name) {
    return this.webClient.get()
        .url("/{id}/details", name)
        .retrieve()
        .bodyToMono(Details.class)
        .doOnNext(this::validate);
  }
}

在实际应用中,您可能希望获得更好格式化的违规信息字符串,如果在多个地方进行验证,您可以将该逻辑提取到自己的类中。

英文:

With a little effort you can use JSR-303 annotation based validation on the POJOs that are returned by a WebClient call. Here's a minimal example:

@Component
public class MyClass {

  final Validator validator;

  MyClass(Validator validator) {
    this.validator = validator;
  }

  &lt;T&gt; T validate(T obj) {

    Set&lt;ConstraintViolation&lt;T&gt;&gt; violations = this.validator.validate(obj);
    if (violations.size() &gt; 0) {
      throw new ResponseStatusException(INTERNAL_SERVER_ERROR, violations.toString());
    }

    return obj;
  }

  public Mono&lt;Details&gt; someRestCall(String name) {
    return this.webClient.get()
        .url(&quot;/{id}/details&quot;, name)
        .retrieve()
        .bodyToMono(Details.class)
        .doOnNext(this::validate);
  }
}

In practice you might want a better formatted violations string and if validation is done in a few places then you could lift that logic into its own class.

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

发表评论

匿名网友

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

确定