Yur*_*kov 7 java spring spring-mvc spring-boot
这是一个问题:我有一个采用输入模型的控制器。可以说
public class AppUserUpdateData {
@NotNull
@Size(min = 1, max = 50)
protected String login;
@JsonDeserialize(using = MyDateTimeDeserializer.class)
protected Date startWorkDate;
*************
other properties and methods
*************
}
Run Code Online (Sandbox Code Playgroud)
问题是,当我想限制某个日期的下限时,尽管我在代码中处理了这种情况,但最终还是会收到 HTTP 异常 400 且没有任何消息!这是一个控制器:
@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;
}
Run Code Online (Sandbox Code Playgroud)
这是一个解串器:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在 a 中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);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,当 a 中的异常MyDateTimeDeserializer被抛出时,它不会落入 aMyExceptionHandler但我不明白为什么?我究竟做错了什么?在响应中只是一个带有代码 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);
}
}
Run Code Online (Sandbox Code Playgroud)
UPD
在我的项目中,没有注释就无法工作,@Order(Ordered.HIGHEST_PRECEDENCE)
我相信这是因为项目中的 ControllerAdvices 数量
小智 7
updateUser在你的控制器被调用之前,它的参数必须被解析。这是HandlerMethodArgumentResolverComposite进来的地方,并委托给预先注册的HandlerMethodArgumentResolvers 之一 - 在这种特殊情况下,它委托给RequestResponseBodyMethodProcessor.
通过委托,我的意思是调用解析器的resolveArgument方法。此方法间接调用deserialize反序列化器中的方法,该方法会引发类型为 的异常MyOwnWrittenException。问题是这个异常被另一个异常包裹了。事实上,当它传播回 时resolveArgument,它的类型是HttpMessageNotReadableException。
因此,与其MyOwnWrittenException在自定义异常处理程序中捕获,不如捕获类型为 的异常HttpMessageNotReadableException。然后,在处理这种情况的方法中,您可以检查“原始”异常MyOwnWrittenException是否确实存在 - 您可以通过重复调用该getCause方法来做到这一点。在我的情况下(它可能与您的情况相同),我需要调用getCause两次以“解开”原始异常(HttpMessageNotReadableException-> JsonMappingException-> MyOwnWrittenException)。
请注意,您不能简单地在异常处理程序中替换MyOwnWrittenExceptionwith HttpMessageNotReadableException,因为它(在运行时)与另一种方法发生冲突,该方法专门设计用于处理后一种类型的异常,称为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...
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2247 次 |
| 最近记录: |