简介
框架的强大之处就在于把很多需要码农多次重复编写的代码剥离出来,形成核心的处理方式。
在异常的处理这块,你不需要再有过多的 try-catch 语句,只需要把异常抛给框架就行了,框架帮你处理!
在 spring mvc 中的统一异常处理有3种,本文拿最简单的一种来演示 。
自定义异常
为了更精确的定位异常,区分异常种类,我们会用到自定义异常。
考虑下如下场景:系统需要提供一个 API,供其它系统查看消息,服务器之间采用 json 交互,这时候我们需要自定一个异常,用来表示逻辑受理失败(比如对方未传必填参数)。
public class ServiceException extends RuntimeException {
private String code;
public ServiceException(String msg) {
super(msg);
}
public ServiceException(String code, String msg) {
super(msg);
this.code = code;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
上面定义了一个自定义异常类 ServiceException ,用来返回错误码及错误信息。
下面我们来看下 service 的代码:
public Message findById(Long id) {
if (id == null) {
throw new ServiceException("10001", "id不能为空!");
}
return messageManager.findOne(id);
}
接受一个 id 的参数,先判断是否为空,如果为空,抛出异常;如果不为空,查找该 id 对应的消息。
接下来,我们有两种选择:
- 在 controller 中使用 try-catch 处理
- 把异常抛给上层框架统一处理
使用 try-catch 处理异常
@RequestMapping("/getMessage")
@ResponseBody
public String getMessage(Long id) {
String result = StringUtils.EMPTY;
try {
Message message = messageService.findById(id);
result = JSON.toJSONString(message);
} catch (ServiceException e) {
JSONObject jb = new JSONObject();
jb.put("msg", e.getMessage());
jb.put("code", e.getCode());
result = JSON.toJSONString(jb);
}
return result;
}
这种方式是不可取的,我们需要对每个方法都加上 try-catch 进行处理。
如果有多种异常,或者说后期又增加了一种异常,维护起来会非常麻烦。
框架统一处理
spring 为我们提供了 ControllerAdvice 机制来统一处理异常,使用起来也比较方便。
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = ServiceException.class)
@ResponseBody
public String handleServiceException(ServiceException e) {
JSONObject jb = new JSONObject();
jb.put("msg", e.getMessage());
jb.put("code", e.getCode());
return JSON.toJSONString(jb);
}
}
这样,我们就能很轻松的统一地去处理异常了。
总结
我们只需要定义一个统一异常处理类,加上 @ControllerAdvice 注解,就能统一地处理异常。
在方法上使用 @ExceptionHandler 注解来处理指定的异常。
《java 编程思想》中说到:
异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。
因此我们要尽量减少异常,更不要用异常进行业务逻辑处理。