Spring MVC @ControllerAdvice异常行为因Exception源而异

时间:2015-02-17 00:31:40

标签: java spring spring-mvc spring-jdbc

根据是否通过调用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);       
}

我真的很想了解为什么根据异常的来源,行为会有所不同。

1 个答案:

答案 0 :(得分:1)

我猜你只是在DKE中设置msg,而在exceptionhandler中你正在做ex.getCause()。getMessage(),我想这是在抛出NPE。尝试使用msg设置Throwable cause并尝试一下。