gpt4 book ai didi

java - 在 ControllerAdvice 之前捕获反序列化异常

转载 作者:行者123 更新时间:2023-11-30 07:46:03 25 4
gpt4 key购买 nike

这里有一个问题:我有一个采用输入模型的 Controller 。让我们说

public class AppUserUpdateData {

@NotNull
@Size(min = 1, max = 50)
protected String login;
@JsonDeserialize(using = MyDateTimeDeserializer.class)
protected Date startWorkDate;
*************
other properties and methods
*************
}

问题是当我想限制日期的下降时,尽管我在我的代码中处理了这种情况,但我最终得到了一个没有任何消息的 HTTP 异常 400!这是一个 Controller :

 @RequestMapping(
value = "/users/{userId}", method = RequestMethod.PUT,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public @ResponseBody AbstractSuccessResult updateUser(@PathVariable Long userId,
@RequestBody AppUserUpdateData appUserUpdateRequest, HttpServletRequest request) {
AbstractSuccessResult response = new AbstractSuccessResult();
appUserService.updateUser(appUserUpdateRequest, userId);
return response;
}

这是一个反序列化器:

public class MyDateTimeDeserializer extends JsonDeserializer<Date> {

@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext context)
throws IOException, JsonProcessingException {
try {
return DataTypeHelper.stringToDateTime(jsonParser.getText());
} catch (MyOwnWrittenException ex) {
throw ex;
}
}
}

DataTypeHelper.stringToDateTime 中是一些阻止无效日期字符串的验证。我的异常有一个处理程序:

@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler({ MyOwnWrittenException .class})
protected ResponseEntity<Object> handleInvalidRequest(RuntimeException exc,
WebRequest request) {

MyOwnWrittenException ex = (MyOwnWrittenException) exc;
BasicErrorMessage message; = new BasicErrorMessage(ex.getMessage());
AbstractUnsuccessfulResult result = new AbstractUnsuccessfulResult(message);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return handleExceptionInternal(exc, result, headers, HttpStatus.BAD_REQUEST, request);
}
}

问题是,当 MyDateTimeDeserializer 中的异常被抛出时,它不会落入 MyExceptionHandler 但我不明白为什么?我究竟做错了什么?在响应中只是一个带有代码 400(

UPD感谢@Joe Doe 的回答,问题已经解决。这是我更新的处理程序:

@Order(Ordered.HIGHEST_PRECEDENCE)    
@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler({ MyOwnWrittenException .class})
protected ResponseEntity<Object> handleInvalidRequest(RuntimeException exc,
WebRequest request) {

MyOwnWrittenException ex = (MyOwnWrittenException) exc;
BasicErrorMessage message; = new BasicErrorMessage(ex.getMessage());
AbstractUnsuccessfulResult result = new AbstractUnsuccessfulResult(message);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return handleExceptionInternal(exc, result, headers, HttpStatus.BAD_REQUEST, request);
}

@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
Throwable cause = ex.getCause();
String message = null;
if (cause instanceof JsonMappingException) {
if (cause.getCause() instanceof MyOwnWrittenException) {
return handleInvalidRequest((RuntimeException) cause.getCause(), request);
} else {
message = cause.getMessage();
}
} else {
message = ex.getMessage();
}
AbstractUnsuccessfulResult result = new AbstractUnsuccessfulResult(
new BasicErrorMessage(message));
headers.setContentType(MediaType.APPLICATION_JSON);
return handleExceptionInternal(ex, result, headers, HttpStatus.BAD_REQUEST, request);
}
}

UPD在我的项目中,如果没有注释 @Order(Ordered.HIGHEST_PRECEDENCE) 它就无法工作我相信这是因为项目中的 ControllerAdvices 数量

最佳答案

之前updateUser在你的 Controller 被调用时,它的参数必须被解析。这是HandlerMethodArgumentResolverComposite的地方进来,代表预先登记的人之一 HandlerMethodArgumentResolver s - 在这种特殊情况下,它委托(delegate)给 RequestResponseBodyMethodProcessor .

委托(delegate)是指调用解析器的 resolveArgument方法。此方法间接调用 deserialize来自反序列化器的方法,它抛出 MyOwnWrittenException 类型的异常.问题是这个异常被包裹在另一个异常中。事实上,当它传播回 resolveArgument 时, 它的类型是 HttpMessageNotReadableException .

所以,而不是捕捉 MyOwnWrittenException在您的自定义异常处理程序中,您需要捕获 HttpMessageNotReadableException 类型的异常.然后,在处理这种情况的方法中,您可以检查“原始”异常是否实际上是 MyOwnWrittenException - 你可以通过重复调用 getCause 来做到这一点方法。在我的情况下(它可能与你的情况相同),我需要调用 getCause两次“展开”原始异常 ( HttpMessageNotReadableException -> JsonMappingException -> MyOwnWrittenException )。

请注意,您不能简单地替换 MyOwnWrittenExceptionHttpMessageNotReadableException在您的异常处理程序中,因为它(在运行时)与另一种方法发生冲突,该方法专门用于处理后一种类型的异常,称为 handleHttpMessageNotReadable .

总而言之,你可以这样做:

@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {

@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
// ex.getCause().getCause().getClass() gives MyOwnWrittenException
// the actual logic that handles the exception...
}
}

关于java - 在 ControllerAdvice 之前捕获反序列化异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51001546/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com