针对特定条件的异常处理 - 最佳实践

时间:2014-06-24 18:11:55

标签: java spring-mvc exception-handling

我在DAO方法中有以下代码:

public void someMethod() throws CustomException {
       try {
           ... do something ...
        }catch(Exception e) {
             if(e.getCause() instanceOf org.hibernate.ConstraintViolationException && e.getMessage().contains("child record found")) {
                  throw new CustomException("Child records found.");
             }else {
                  throw new CustomException("Unable to update.");
             }
        }
}

在服务层:

public void someMethod() throws CustomException {
 dao.someMethod();
}

在控制器中:

public ResponseObject someMethod() {
  ResponseObject response = new ResponseObject();
  try {
    service.someMethod();
    response.setMessage("success");
  }catch(CustomException e) {
    response.setMessage(e.getMessage());
  }
  return response;
}

我是否按照最佳做法正确行事? 我还能做些什么来使它成为正确的?

任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:0)

我注意到的一些事情。首先,仅在特殊情况下使用例外。换句话说,例外应该是例外,而不是常态。从它的外观来看,“ConstraintViolationException”是预期很多的东西。 异常会使代码更加难以调试,并且可以减少JVM优化,从而大大加快程序执行速度。

其次,如果调用者可以合理地预期恢复,则应该只使用已检查的异常(不从RuntimeException扩展的异常)。在您的情况下,除了给客户端一个错误消息之外,调用者不会做任何事情来恢复。 通过抛出已检查的异常,可以强制调用者在catch子句中处理异常或将其向外传播。 (两者都是这些陷阱,详见Joshua Bloch的优秀着作“Effective Java”。)

第三,在异常处理中,您尝试解析错误消息。这可能是非常有问题的,因为第三方经常更改其错误消息,因为它们 不属于API的一部分。一旦发生这种情况,您的代码就会被破坏。异常处理中的另一个小问题是将JPA实现与hibernate联系起来。如果以后要更改为EclipseLink会怎么样?

有办法解决所有这些问题 摆脱DAO中的异常处理。 将以下方法添加到DAO:

boolean childRecordExists(Record record)

然后,在你的控制器中,有类似的东西:

if (service.childRecordExists()){
   response.setMessage("Failed.  A child record exists");  //a useful error message for the user, as you know *exactly* why failure happened
} else {
    service.someMethod();
    response.setMessage("Success");
}

您需要在控制器中使用某种exceptionHandler。 (如果您使用的是Spring MVC,则可以使用ExceptionHandler注释将其添加为另一种方法。) 这将解决真正例外的事情(日常用户体验不同寻常的事情,以及用户无法修复的事情。)