Webflux WebClient中如何自定义异常?

Posted

技术标签:

【中文标题】Webflux WebClient中如何自定义异常?【英文标题】:How do custom exception in Webflux WebClient? 【发布时间】:2019-12-30 08:00:26 【问题描述】:

在我的 webflux 应用程序中,我想通过 WebClient 发送一些请求。我想处理所有条件(200401403... 响应),然后响应json 到客户端。对于错误状态代码,我想使用@RestControllerAdvice,所以我必须抛出一个自定义异常,然后在控制器建议中处理自定义 json。查看示例代码:

WebClient.create().post
   .uri("URI")
   .retrieve()
   .onStatus(HttpStatus::is4xxClientError, 
       // create Mono<CustomException> 
   
   .bodyToMono(ResponseDto.class)

现在异常处理程序如下:

@ResponseBody
@ResponseStatus(...)
@ExceptionHandler(CustomException1.class)
public void customException1(CustomException1 exception) 
   //do Something width response body


@ExceptionHandler(CustomException2.class)
public void customException2(CustomException2 exception) 
   //do Something width response body

Webclient 得到一个 401 响应,json 正文如下:


   "message": "Password is incorrect"

我可以创建Mono.error(new CustomException()),但问题是 WebClient 响应体。如果消息是“密码不正确”,我想发送客户端:

用户名或密码不正确

我该怎么做?

【问题讨论】:

你能澄清一下这里的实际和预期结果是什么吗?是否要更改异常处理程序或 Web 客户端代码? @MartinTarjányi 用户发送 ajax 请求,而 Whit 请求参数我向服务器发送请求。我想在失败模式下响应用户不同的答案。所以我想用异常处理程序来做。 有多种方法可以解决这个问题,而您提供的信息太少。您要解决的实际问题是什么,如果您是 webflux 的新手,为什么要So I want do it with Exception Handler。 Webflux 不像 spring boot,你使用 webflux 解决不同的事情。如果你在抛出异常时解释你想要做的更详细的事情。想要登录吗?向客户端返回http状态?提出新要求? 【参考方案1】:

请检查以下处理调用的 rest api 调用的错误响应的 API 实现。我假设我们知道 api 的响应,所以我创建了 ResponseDTO 类。

Controller.java

@GetMapping("/webclient/test")
public ResponseDTO testWebclient(@RequestBody RequestDTO requestPayload) 
    String url = "http://localhost:8080/api/write/simple";
    return WebClient.create()
            .post()
            .uri(url)
            .accept(MediaType.APPLICATION_JSON)
            .body(BodyInserters.fromObject(requestPayload))
            .retrieve()
            .onStatus(HttpStatus::is4xxClientError, response -> 
                return response.bodyToMono(ResponseDTO.class).flatMap(error -> 
                    return Mono.error(new CustomRuntimeException(error.getMessage(), response.statusCode(), error.getErrorCode()));
                );
            )
            .onStatus(HttpStatus::is5xxServerError, response -> 
                return response.bodyToMono(ResponseDTO.class).flatMap(error -> 
                    return Mono.error(new CustomRuntimeException(error.getMessage(), response.statusCode()));
                );
            )
            .bodyToMono(ResponseDTO.class);

ResponseDTO.java

public class ResponseDTO 

    private String message;
    private HttpStatus status;
    private ErrorCode errorCode;
    
    public ResponseDTO(String message, HttpStatus status) 
        this.message = message;
        this.status = status;
    

    public ResponseDTO(String message, HttpStatus status, ErrorCode errorCode) 
        this.message = message;
        this.status = status;
        this.errorCode = errorCode;
    
    /** getters **/

ErrorCode.java

    public class ErrorCode 
        private String numCode;
        private String txtCode;
        
        /** getters **/
    

要捕获异常,请在@RestControllerAdvice 的类中添加以下代码 sn-p(希望您已经知道)。

@ExceptionHandler(value = CustomRuntimeException.class)
public final ResponseEntity<ApiResponse> handleCustomRuntimeException(CustomRuntimeException exception) 
    List<ApiSubError> subErrors = Arrays.asList(new ApiSubError(exception.getMessage()));
    ApiResponse response = new ApiErrorResponse(exception.getMessage(), exception.getErrorCode());
    LOG.error("result: ", response.getResult());
    return new ResponseEntity<>(response, exception.getHttpStatus());

【讨论】:

我需要 webclient 响应正文。我想把它发给我的客户。 请检查我在回答中给出的参考资料。 同样的结果。问题是:获取 Webclient 错误响应正文并将其发送给客户端 我已经更新了运行良好的答案。我希望这就是你要找的。为了完成这项工作,我花了 2 个小时,我自己也学会了。【参考方案2】:

我从未使用过 WebFlux,但我找到了 Add Exception handler for Spring Web Client。看起来您可以通过在 onStatus 处理函数中编写 return Mono.error(new CustomException1()); 来引发异常。根据描述,bodyToMono(Class)方法会抛出异常。

最后,您可以像这样修改您的 ControllerAdvice:

@ExceptionHandler(CustomException.class)
public ResponseEntity<CustomErrorModel> customException(CustomException exception) 
   return new ResponseEntity<>( new CustomErrorModel(), HttpStatus.BAD_REQUEST );

正如我所说 - 我没有测试它,但它可能是给你的一个提示。

【讨论】:

以上是关于Webflux WebClient中如何自定义异常?的主要内容,如果未能解决你的问题,请参考以下文章

(WebFlux)001如何自定义注解实现功能

(WebFlux)001如何自定义注解实现功能

(WebFlux)001如何自定义注解实现功能

在 WebFlux WebClient 中测试状态码时如何获取响应正文?

WebFlux系列WebClient 异常处理

如何使用 Spring Boot 对 WebFlux 进行异常处理?