Spring MVC @ControllerAdvice 异常行为因异常源而异
Spring MVC @ControllerAdvice exception behavior different based on Exception source
取决于 DuplicateKeyException (DKE) 是通过调用 NamedParameterJdbcTemplate(即 jdbcTemplate.update(sql, namedParameter))还是由我在代码中明确抛出,行为是非常不一样。
当 jdbcTemplate 调用抛出 DKE 时,会发生正确的行为。我的@ControllerAdvice 启动,正确的 HTTP 状态和 ResponseBody 被 returned。但是,当我明确抛出 DKE 时,return 向客户端发送了一个 500 错误,即使我看到我的 @ControllerAdvice class 中的正确代码块正在被访问。
这是处理异常的代码,它应该总是 return HttpStatus.OK 以及一个 RestError:
@ExceptionHandler(DuplicateKeyException.class)
@ResponseStatus(value = HttpStatus.OK)
public @ResponseBody RestError handleDuplicateKey(
HttpServletRequest request, Exception ex) {
logger.error("GlobalExceptionHandler handling exception of type DuplicateKeyException.class: ", ex);
return new RestError(HttpStatus.CONFLICT,
ErrorCode.DUPLICATE_ENTRY,
ex.getCause().getMessage());
}
下面是可以抛出 DKE 的代码:
public void insertSubscriber(SubscriberInfo subscriberInfo) {
if (isAlreadySubscribed(subscriberInfo)) {
// this will result in a 500 http error to the client
throw new DuplicateKeyException(
String.format("This subscriber is already subscribed");
}
String sql = "INSERT INTO subscribers (firstname, email, postal_code, subscriber_type) "
+ "VALUES (:firstname, :email, :postal_code, :subscriber_type)";
HashMap<String, String> namedParameter = Maps.newHashMapWithExpectedSize(4);
namedParameter.put("email", subscriberInfo.getEmail());
namedParameter.put("postal_code", subscriberInfo.getPostalCode());
namedParameter.put("subscriber_type", subscriberInfo.getUserType().getId());
namedParameter.put("firstname", subscriberInfo.getFirstname());
// if a DKE is thrown from the below line, everything works fine.
jdbcTemplate.update(sql, namedParameter);
}
我真的很想了解为什么行为会根据异常的来源而有所不同。
我猜你只是在 DKE 中设置消息,而在异常处理程序中你正在做 ex.getCause().getMessage() 我猜这是抛出 NPE。尝试使用 msg 设置 Throwable cause 并试一试。
取决于 DuplicateKeyException (DKE) 是通过调用 NamedParameterJdbcTemplate(即 jdbcTemplate.update(sql, namedParameter))还是由我在代码中明确抛出,行为是非常不一样。
当 jdbcTemplate 调用抛出 DKE 时,会发生正确的行为。我的@ControllerAdvice 启动,正确的 HTTP 状态和 ResponseBody 被 returned。但是,当我明确抛出 DKE 时,return 向客户端发送了一个 500 错误,即使我看到我的 @ControllerAdvice class 中的正确代码块正在被访问。
这是处理异常的代码,它应该总是 return HttpStatus.OK 以及一个 RestError:
@ExceptionHandler(DuplicateKeyException.class)
@ResponseStatus(value = HttpStatus.OK)
public @ResponseBody RestError handleDuplicateKey(
HttpServletRequest request, Exception ex) {
logger.error("GlobalExceptionHandler handling exception of type DuplicateKeyException.class: ", ex);
return new RestError(HttpStatus.CONFLICT,
ErrorCode.DUPLICATE_ENTRY,
ex.getCause().getMessage());
}
下面是可以抛出 DKE 的代码:
public void insertSubscriber(SubscriberInfo subscriberInfo) {
if (isAlreadySubscribed(subscriberInfo)) {
// this will result in a 500 http error to the client
throw new DuplicateKeyException(
String.format("This subscriber is already subscribed");
}
String sql = "INSERT INTO subscribers (firstname, email, postal_code, subscriber_type) "
+ "VALUES (:firstname, :email, :postal_code, :subscriber_type)";
HashMap<String, String> namedParameter = Maps.newHashMapWithExpectedSize(4);
namedParameter.put("email", subscriberInfo.getEmail());
namedParameter.put("postal_code", subscriberInfo.getPostalCode());
namedParameter.put("subscriber_type", subscriberInfo.getUserType().getId());
namedParameter.put("firstname", subscriberInfo.getFirstname());
// if a DKE is thrown from the below line, everything works fine.
jdbcTemplate.update(sql, namedParameter);
}
我真的很想了解为什么行为会根据异常的来源而有所不同。
我猜你只是在 DKE 中设置消息,而在异常处理程序中你正在做 ex.getCause().getMessage() 我猜这是抛出 NPE。尝试使用 msg 设置 Throwable cause 并试一试。