java - @RestControllerAdvice 在 Spring Boot 反应式 Java 应用程序中不起作用
问题描述
我目前正在抛出一个自定义异常 - RequestValidationException
。
ExceptionHandler
类:
@RestControllerAdvice
@Slf4j
public class RestExceptionHandler {
@ExceptionHandler(value = RequestValidationException.class)
@ResponseStatus(HttpStatus.PRECONDITION_FAILED)
public Mono<HttpValidationError> handleRequestValidationException(RequestValidationException exception) {
log.error("Received exception: ", exception);
List<String> loc = new ArrayList<>();
loc.add(exception.getMessage());
ValidationError validationError = ValidationError.builder()
.loc(loc)
.msg(exception.getMessage())
.build();
List<ValidationError> errorMessages = new ArrayList<>();
errorMessages.add(validationError);
return Mono.just(HttpValidationError.builder().detail(errorMessages).build());
}
RequestValidationException
类:
public class RequestValidationException extends RuntimeException {
public static final HttpStatus statusCode = HttpStatus.PRECONDITION_FAILED;
public RequestValidationException(String text) {
super(text);
}
public HttpStatus getStatusCode() {
return statusCode;
}
}
当exception
被抛出时,我想要以下内容response
:
Code: 412
{
"detail": [
{
"loc": [
"No ID found to update. Please add an ID"
],
"msg": "No ID found to update. Please add an ID",
"type": null
}
]
}
我收到的是:
{
"error_code": 500,
"message": "No ID found to update. Please add an ID"
}
我检查了应用程序日志,没有任何地方RestExceptionHandler
被调用。它只是记录这个error
:
"level":"ERROR","logger":"c.a.c.c.c.AbstractController","thread":"boundedElastic-1","message":"Controller exception","stack":"<#384d845f> c.a.c.a.e.RequestValidationException
我似乎无法弄清楚这段代码有什么问题。有人可以指出我可能缺少什么吗?谢谢。
解决方案
我只能通过以下实现来实现AbstractErrorWebExceptionHandler
它(对于 kotlin 代码感到抱歉):
@Component
@Order(-2)
class GlobalExceptionHandler(errorAttributes: ErrorAttributes,
resources: WebProperties.Resources,
applicationContext: ApplicationContext,
serverCodecConfigurer: ServerCodecConfigurer) : AbstractErrorWebExceptionHandler(errorAttributes, resources, applicationContext) {
companion object {
private val logger = KotlinLogging.logger {}
private const val HTTP_STATUS_KEY = "status"
private const val MESSAGE_KEY = "message"
private const val ERRORS_KEY = "errors"
}
init {
setMessageWriters(serverCodecConfigurer.writers)
}
override fun setMessageWriters(messageWriters: MutableList<HttpMessageWriter<*>>?) {
super.setMessageWriters(messageWriters)
}
override fun getRoutingFunction(errorAttributes: ErrorAttributes?): RouterFunction<ServerResponse> {
return RouterFunctions.route({ true }) { request ->
val error: Throwable = getError(request)
logger.error("Handling: ", error)
val errorProperties = getErrorAttributes(request, ErrorAttributeOptions.defaults())
when (error) {
is WebExchangeBindException -> {
....
}
else -> {
...
}
}
ServerResponse.status(HttpStatus.valueOf(errorProperties[HTTP_STATUS_KEY] as Int))
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(errorProperties)
}
}
}
在 Java 中会是这样的:
@Component
@Order(-2)
public class GlobalExceptionHandler extends AbstractErrorWebExceptionHandler {
private static final String HTTP_STATUS_KEY = "status";
private static final String MESSAGE_KEY = "message";
private static final String ERRORS_KEY = "errors";
public GlobalExceptionHandler(ErrorAttributes errorAttributes, Resources resources, ApplicationContext applicationContext, ServerCodecConfigurer serverCodecConfigurer) {
super(errorAttributes, resources, applicationContext);
this.setMessageWriters(serverCodecConfigurer.getWriters());
}
public final void setMessageWriters(List messageWriters) {
super.setMessageWriters(messageWriters);
}
protected RouterFunction getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}
private Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
Map<String, Object> errorPropertiesMap = getErrorAttributes(request,
ErrorAttributeOptions.defaults());
return ServerResponse.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorPropertiesMap));
}
}
您可以在https://www.baeldung.com/spring-webflux-errors#global查看更多详细信息。
推荐阅读
- python - 如何提示向用户询问文件名的用户?
- javascript - 无法从光标填充数组
- node.js - sqlite3中的主键是如何自动分配的?
- android - 从父视图获取特定类型的视图
- javascript - 删除重复的 GeoJSON 线串,同时支持具有更多属性的对象。在 Javascript 中
- json - 如何合并从 S3 读取的多个 JSON 文件,转换为单个 .csv 并存储在 S3 中?
- c# - ASP.NET Core Identity - 确认电子邮件返回 url
- android - 映射对象时某些属性为空时忽略元素
- c++ - 将变量从函数 A 传递到 main 并返回到另一个
- python - 如何将 get_tld 库用于数据集中的整个列?