如何在 Webflux WebClient 中自定义异常?
How do custom exception in Webflux WebClient?
在我的 webflux 应用程序中,我想通过 WebClient 发送一些请求。我想处理所有条件(200、401、403 和 .. . 响应),然后向客户端响应 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 响应正文。如果消息是"Password is incorrect",我想发送客户端:
Username or Password is incorrect
我该怎么做?
我从未使用过 WebFlux,但我找到了 。看起来您可以通过在 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 );
}
正如我所说 - 我没有测试它,但它可能对你有所提示。
请检查以下 API 实现,它处理调用的 rest api 调用的错误响应。我假设我们知道 api 的响应,所以我创建了 ResponseDTO
class.
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
的 class 中添加以下代码片段(希望您已经知道)。
@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());
}
在我的 webflux 应用程序中,我想通过 WebClient 发送一些请求。我想处理所有条件(200、401、403 和 .. . 响应),然后向客户端响应 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 响应正文。如果消息是"Password is incorrect",我想发送客户端:
Username or Password is incorrect
我该怎么做?
我从未使用过 WebFlux,但我找到了 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 );
}
正如我所说 - 我没有测试它,但它可能对你有所提示。
请检查以下 API 实现,它处理调用的 rest api 调用的错误响应。我假设我们知道 api 的响应,所以我创建了 ResponseDTO
class.
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
的 class 中添加以下代码片段(希望您已经知道)。
@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());
}