异常不可避免,设计主要考虑以下原则
- 程序错误导致异常:客户端无能为力
- 客户端行为导致异常:如果能识别出来原因并通知客户端,否则客户端也无能为力
- 请求资源失败导致异常:客户端可能可以补救,也许也无能为力如系统资源耗尽
基于上述分类,java里面的异常设计基本遵循以下两条原则
客户端无能为力 -- 封装成Unchecked
客户端可以调整 -- 封装成Checked
一些好的实践
- Try not to create new custom exceptions if they do not have useful information for client code.
bad:
public class DuplicateUsernameException extends Exception {}
good:
public class DuplicateUsernameException extends Exception {
public DuplicateUsernameException (String username){....}
public String requestedUsername(){...}
public String[] availableNames(){...}
}
or even:
throw new RuntimeException("Username already taken");
-
Never use exceptions for flow control
-
Generating stack traces is expensive and the value of a stack trace is in debugging. In a flow-control situation, the stack trace would be ignored, since the client just wants to know how to proceed.
Spring的异常处理
三种选择:以异常为基础;以控制器为基础;全局处理
任何没有被处理的异常会导致HTTP 500错误。
- 以异常为基础
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="No such Order") // 404
public class OrderNotFoundException extends RuntimeException {
// ...**Bad practice according above principle**
}
这种异常不需要特殊处理,也不需要在最外层拦截,会直接导致一个指定HTTP状态的返回。
- 以控制器为基础
可以在Controller范围内对异常进行处理
可以使用@ExceptionHandler,也可以使用@ExceptionHandler和@ResponseStatus相结合,可以定制HTTP返回(既可以是View--使用ModelAndView,也可以是String,也可以没有返回)
HttpServletRequest, HttpServletResponse, HttpSession and/or Principle都可以出现在handler的参数列表里。
- 全局处理
@ControllerAdvice
每一个处理方法都需要使用@ExceptionHandler
网友评论