Spring Boot 框架异常处理有五种处理方式,从范围来说包括有全局异常捕获处理方式和局部异常捕获处 理方式
自定义异常错误页 在遇到异常时,Spring Boot 会自动跳到一个默认的异常页面,如请求上述 http://localhost:8080/exceptionMethod 路径时发生 500 错误,Spring Boot 会有一个默认的页面 展示给用户,如图所示
Spring Boot 默认的异常处理机制是程序中出现了异常 Spring Boot 就会请求 /error 的 url 。
这里以 Thymleaf 为例,Thymleaf 页面模板默认处于 classpath:/templates/ 下, 因此在该目录下创建 error.html 文件即可
使用@ExceptionHandler注解处理局部异常
SpringMVC 提供了@ExceptionHandler 这个注解,在 SpringBoot 里面,我们同样可以 使用它来做异常捕获。直接在对应的 Controller 里面增加一个异常处理的方法,并使用 @ExceptionHandler 标识它即可,属于局部处理异常
@Controller public class ExceptionController { private static final Logger log = LoggerFactory.getLogger(ExceptionController.class); @RequestMapping("/exceptionMethod") public String exceptionMethod(Model model) throws Exception { model.addAttribute("msg", "没有抛出异常"); int num = 1/0; log.info(String.valueOf(num)); return "index"; } /** * 描述:捕获 ExceptionController 中的 ArithmeticException 异常 * @param model 将Model对象注入到方法中 * @param e 将产生异常对象注入到方法中 * @return 指定错误页面 */ @ExceptionHandler(value = {ArithmeticException.class}) public String arithmeticExceptionHandle(Model model, Exception e) { model.addAttribute("msg","@ExceptionHandler" + e.getMessage()); log.info(e.getMessage()); return "error"; } }
使用 @ControllerAdvice 注解处理全局异常 实际开发中,需要对异常分门别类的进行处理,使用 @ControllerAdvice + @ExceptionHandler 注解能够处理全局异常,这种方式推荐使用,可以根据不同的异常对不 同的异常进行处理。 使用方式:定义一个类,使用 @ControllerAdvice 注解该类,使用 @ExceptionHandler 注解方法,这里我定义了一个 GlobalException 类表示来处理全局异常,代码如下: //GlobalException.java @ControllerAdvice public class GlobalException { private static final Logger log = LoggerFactory.getLogger(GlobalException.class); /** * 描述:捕获 ArithmeticException 异常 * @param model 将Model对象注入到方法中 * @param e 将产生异常对象注入到方法中 * @return 指定错误页面 */ @ExceptionHandler(value = {ArithmeticException.class}) public String arithmeticExceptionHandle(Model model, Exception e) { model.addAttribute("msg", "@ControllerAdvice + @ExceptionHandler :" + e.getMessage()); log.info(e.getMessage()); return "error"; } }
如果需要处理其他异常,如 NullPointerException 异常,则只需要在 GlobalException 类 中定义一个方法使用 @ExceptionHandler(value = {NullPointerException.class}) 注解该方法, 在该方法内部处理异常就可以了。
配置 SimpleMappingExceptionResolver 类处理异常 通过配置 SimpleMappingExceptionResolver 类处理异常也是全局范围的,通过将 SimpleMappingExceptionResolver 类注入到 Spring 容器,代码如下: @Configuration public class GlobalException { @Bean public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){ SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); Properties mappings = new Properties(); /* * 参数一:异常的类型,注意必须是异常类型的全名 * 参数二:视图名称 */ mappings.put("java.lang.ArithmeticException", "error"); //设置异常与视图映射信息的 resolver.setExceptionMappings(mappings); return resolver; } }
实现 HandlerExceptionResolver 接口处理异常 通过实现 HandlerExceptionResolver 接口处理异常,首先编写类实现 HandlerExceptionResolver 接口,代码如下: @Configuration public class HandlerExceptionResolverImpl implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("msg", "实现 HandlerExceptionResolver 接口处理异常"); //判断不同异常类型,做不同视图跳转 if(ex instanceof ArithmeticException){ modelAndView.setViewName("error"); } return modelAndView; } }
当然了,异常很多,比如还有 RuntimeException,数据库还有一些查询或者操作异常等 等。由于 Exception 异常是父类,所有异常都会继承该异常,所以我们可以直接拦截 Exception 异常,一劳永逸,代码如下: @ControllerAdvice public class GlobalException{ private static final Logger log= LoggerFactory.getLogger(GlobalException.class); /** * 系统异常 预期以外异常 * @param e * @return */ @ExceptionHandler(Exception.class) //@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public JsonResult handleUnexpectedServer(Model model,Exception ex) { model.addAttribute("msg", "系统发生异常,请联系管理员"); log.info(e.getMessage()); return "error"; } } 实际项目中,可以把拦截 Exception 异常写在 GlobalException最下面,如果都没有找到,最后再拦截一下 Exception 异常,保证异常得到处理。