现有的方案中Controller中的每个Handler自己处理异常,这种异常处理的异常处理逻辑分散在各个Handler中,不利于集中管理。为此,Spring提供了一个全局异常捕获的功能--->异常解析器,这个功能在集中管理异常的方面,对比传统的方法更有优势。
异常解析器共有三种处理方式:
1.实现 HandlerExceptionResolver接口(掌握)
2.通过 @ExceptionHandler 注解定义(掌握)
3.SimpleMappingExceptionResolver(XML文件配置,了解即可)
Maven配置方面:javax.servlet-api ,spring-webmvc ,javax.servlet.jsp-api
因为SpringMVC是一个Web项目,所以还需要在配置方面打成War包。
打成War包后,在main文件下导入webapp,把WEB-INF/web.xml文件剪切放在webapp下。
web.xml配置如下:
在resource包下新建 XMLSpringConfig 配置文件,spring-servlet.xml配置文件如下:
注意:注解注入必须要配置包扫描,相当于把当前包下的加上注解的类或者方法注册到Spring容器中,将来可以拿出来用。
此处先创建一个测试类,在类里面任意定义一个报错的方法:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*Controller类上加了 @RestController 注解,等价于在类中的每个方法上都加了 @ResponseBody
*@ResponseBody 将handler的返回值,转换成json(jackson),并将json响应给客户端
*/
@RestController
public class errorTest {
@GetMapping("/test")
//RequestMapping("/test")
public void hello() {
int i = 1 / 0;
}
}
新建一个捕获全局异常的包,包结构如下:
方法一:
/**
* 自定义全局异常处理器,这个全局异常处理器只需要注册到 Spring 容器中,就会生效
*/
@Component
public class GlobalException implements HandlerExceptionResolver {
/**
* 具体的异常处理方法,所有的异常都会进入到这个方法中
* @param req
* @param resp
* @param handler 抛出异常的处理器
* @param ex 具体的异常
* @return 返回值就是一个异常页面,这里的返回值用法和 Controller 中的完全一致
*/
@Override
public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse resp, Object handler, Exception ex) {
ModelAndView mv = new ModelAndView();
//定义 error.jsp 页面,页面负责收集 Exception,视图解析器将通过该名字跳转到jsp页面
mv.setViewName("error");
mv.addObject("error", ex.getMessage());
return mv;
}
}
jsp页面如下:
方法二:
/**
* 定义全局异常处理器
*
* @ControllerAdvice 这是一个增强的处理器,其他的处理器抛异常,都会进入到这个里边来
*
* 这里定义的每个方法和普通的 controller 是一模一样的
*/
@ControllerAdvice
//@RestControllerAdvice
public class GlobalException2 {
/**
* @ExceptionHandler 用来指定该方法要处理的异常
* @return
*/
//该注解的参数表示需要捕获的异常类型,Exception表示捕获所有异常
@ExceptionHandler(Exception.class)
public String exceptionHandler(Exception e, Model model) {
//调用 addAttribute 方法,将来渲染到jsp页面上
model.addAttribute("error", e.getMessage());
//将来返回error.jsp页面
return "error";
}
}
方法三:
SimpleMappingExceptionResolver异常解析器并不常用,原因是一种类型的异常需要写一个jsp页面,虽然代码耦合性不高,但是需要编写数个jsp页面展示异常,SpringMVC异常捕获中并没有前面两种方式常用。