根据是否通过调用NamedParameterJdbcTemplate(即jdbcTemplate.update(sql,namedParameter))抛出DuplicateKeyException(DKE)或者在代码中由我显式抛出,行为是非常不同的。
当jdbcTemplate调用抛出DKE时,会发生正确的行为。我的@ControllerAdvice启动并返回正确的HTTP状态和ResponseBody。但是当我显式抛出DKE时,即使我看到正在访问@ControllerAdvice类中的正确代码块,也会向客户端返回500错误。
这里是处理异常的代码,它应该总是返回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);
}
我真的很想了解为什么根据异常的来源,行为会有所不同。
答案 0 :(得分:1)
我猜你只是在DKE中设置msg,而在exceptionhandler中你正在做ex.getCause()。getMessage(),我想这是在抛出NPE。尝试使用msg设置Throwable cause并尝试一下。