【问题标题】:How to get custom error body message in WebClient properly?如何在 WebClient 中正确获取自定义错误正文消息?
【发布时间】:2020-12-21 08:55:05
【问题描述】:

我想要实现的是使用 404 代码获取我的响应错误和使用 WebClient 的错误正文,我该如何正确地做到这一点?

这是我的错误代码 404 的响应和来自另一个 API 的正文响应:

{
  "timestamp": "2020-09-02T07:36:01.960+00:00",
  "message": "Data not found!",
  "details": "uri=/api/partnershipment/view"
}

这是我的消费代码的样子:

    Map<String,Long> req = new HashMap<String,Long>();
    req.put("id", 2L);

    PartnerShipmentDto test = webClient.post()
    .uri(urlTest).body(Mono.just(req), PartnerShipmentDto.class)
    .exchange()
    .flatMap(res -> {
        if(res.statusCode().isError()){
            res.body((clientHttpResponse, context) -> {
                throw new ResourceNotFound(clientHttpResponse.getBody().toString());
            });
            throw new ResourceNotFound("aaaa");

        } else {
            return res.bodyToMono(PartnerShipmentDto.class);
        }
    })
    .block();

这是我的 ResourNotFound.java 类:

@SuppressWarnings("serial")
@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFound extends RuntimeException {
    
    public ResourceNotFound(String message){
        super(message);
    }
    
}

这是我使用 @ControllerAdvice 的全局异常处理程序:

@ControllerAdvice
@RestController
public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    public final ResponseEntity<Object> handleAllException(Exception ex, WebRequest request) {

        ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));
        logger.error(ex.getMessage());
        return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(ResourceNotFound.class)
    public final ResponseEntity<Object> handleResourceNotFoundException(ResourceNotFound ex, WebRequest request) {

        ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));
        logger.error(ex.getMessage());
        return new ResponseEntity(exceptionResponse, HttpStatus.NOT_FOUND);
    }

}

但我在 ResourceNotFound 异常中得到的响应是这样的(这是我从消费者方面的错误):

{
  "timestamp": "2020-09-02T07:50:48.132+00:00",
  "message": "FluxMap",
  "details": "uri=/api/shipmentaddressgrouping/store"
}

它只写了“FluxMap”,我如何获得“消息”字段?我也想获取“时间戳”和“详细信息”字段

【问题讨论】:

    标签: java spring-boot spring-webflux spring-webclient


    【解决方案1】:

    您提供的示例代码的主要问题是以下代码行

    throw new ResourceNotFound(clientHttpResponse.getBody().toString());
    

    这个类型是Flux&lt;DataBuffer&gt;,而不是实际的响应正文。这导致了您所看到的问题。

    解决这个问题的方法是在错误响应体上调用bodyToMono 方法并映射到一个java 对象。这可以通过 Web 客户端的 onStatus 操作符公开来完成,它允许您对特定状态代码采取特定操作。

    下面的代码 sn-p 应该可以解决这个问题

        webClient.post()
                .uri(uriTest).body(Mono.just(req), PartnerShipmentDto.class)
                .retrieve()
                .onStatus(HttpStatus::isError, res -> res.bodyToMono(ErrorBody.class)
                        .onErrorResume(e -> Mono.error(new ResourceNotFound("aaaa")))
                        .flatMap(errorBody -> Mono.error(new ResourceNotFound(errorBody.getMessage())))
                )
                .bodyToMono(PartnerShipmentDto.class)
                .block();
    

    ErrorBody 类应该包含您想要从 json 映射到 java 对象的所有字段。下面的示例仅映射“消息”字段。

    public class ErrorBody {
        private String message;
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
    

    【讨论】:

    • 哇它解决了我的错误信息,只是为了让我清醒一下,我读到某处说,如果我们使用 retreive(),我们无法获得错误状态,这导致我改变了我的从retrieve() 到exchange() 的代码,但是你让retrieve() 工作,我什么时候应该使用retrieve() 或exchange()?
    • 我建议尽可能多地使用retrieve(),因为这是javadocs 中推荐的。阅读下面文档中的注释以获取解释docs.spring.io/spring/docs/current/javadoc-api/org/…
    • 非常感谢迈克尔的解释,这让我很开心:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 2011-02-02
    • 2018-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    相关资源
    最近更新 更多