全局异常处理
首先我们对于异常,我们定义了两大类
1.预期异常
可能发生的异常
2.运行期异常
不可预测的异常
参考如下图我们需要知道系统在哪里处理异常,由于service层涉及到事务回滚,必须将异常抛出(系统检测到异常就启动通过代理模式,执行事务回滚代码)
而在controller层,前端控制器定义了事务处理的接口,我们可以自定义异常处理实现类,来实现对于异常的处理
1.定义自定义异常类
//作用:用来装载自定义异常信息
public class CustomException extends Exception {
private String message;
public CustomException(String message) {
super();
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
2.定义异常处理器实现类,实现DispatcherServlet里面的HandlerExceptionResolver接口,这样该异常处理类就变成了全局异常处理类
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
ModelAndView modelAndView = new ModelAndView();
// 处理异常,返回自定义异常处理
CustomException exception = null;
if (ex instanceof CustomException) {
// 预期异常
exception = (CustomException) ex;
} else {
// 非预期异常
exception = new CustomException("未知错误");
}
// 获取异常信息
String message = exception.getMessage();
// 将异常处理信息返回到错误页面
modelAndView.addObject("message", message);
modelAndView.setViewName("/WEB-INF/jsp/error.jsp");
return modelAndView;
}
}
3.配置异常处理实现类,将其交给SpringMVC容器
<!--全局异常处理器 -->
<bean class="com.ncs.exception.CustomExceptionResolver"></bean>
4.在Handler层(Controller)将异常抛出throws Exception,交给前端控制器的自定义全局异常处理器处理,执行异常处理器,判断该异常属于开发人员自定义的异常(预期异常)还是未知的异常(运行期异常,不可预测)
@RequestMapping(value = "/getUserById", method = { RequestMethod.GET })
public ModelAndView getUserById(Integer Id) throws Exception {
ModelAndView modelAndView = new ModelAndView();
List<User> result = userService.getUserById(Id);
// 指定model
modelAndView.addObject("result", result);
// 指定视图
modelAndView.setViewName("/WEB-INF/jsp/show.jsp");
return modelAndView;
}
5.注意: 由于在service层里面我们不能进行异常处理,只能抛出异常(涉及到Spring事务,代理模式,事务回滚)
所以我们可以发现,service层也可以直接抛出自定义异常,这样会被Controller层接着抛出,被异常处理器处理。并且这样存在一个好处可以精确异常信息,业务异常我们也可以精确抛出
@Override
//在查询时,会先在缓存中查找数据,当缓存中数据不存在时,才会执行之后方法查找数据库
@Cacheable(value="cacheTest")
public List<User> getUserById(Integer id) throws Exception {
UserExample example = new UserExample();
Criteria criteria = example.createCriteria();
criteria.andIdEqualTo(id);
List<User> result = userMapper.selectByExample(example);
if(result.isEmpty()) {
throw new CustomException("无该ID用户");
}
return result;
}