SpringMVC笔记06 异常处理与拦截器
coconutnut

https://www.bilibili.com/video/BV1Sb411s7qa

P39~45

异常处理

如果什么都不做,产生异常时(模拟可以除0),会出现500 Internal Server Error

教务系统就是这样🙃

解决步骤

  1. 编写自定义异常类(用作提示信息)
  2. 编写异常处理器
  3. 配置异常处理器(跳转到提示页面)

自定义异常类

1
2
3
4
5
6
7
8
public class SysException extends Exception{

// 存储提示信息
private String message;

// get set constructor ...

}

控制器

捕获异常,抛自定义异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping("/testException")
public String testException() throws SysException{

try {
// 模拟异常
int a = 10/0;
} catch (Exception e) {
e.printStackTrace();
// 抛出自定义异常信息
throw new SysException("查询所有用户出现错误了...");
}

return "success";
}

异常处理器

实现HandlerExceptionResolver接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class SysExceptionResolver implements HandlerExceptionResolver{

// 处理异常的逻辑
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 获取到异常对象
SysException e = null;
if(ex instanceof SysException){
e = (SysException)ex;
}else{
e = new SysException("系统正在维护....");
}
// 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",e.getMessage());
mv.setViewName("error");
return mv;
}

}

配置异常处理器

在springmvc.xml中

1
2
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>

错误提示页面

1
2
3
4
5
6
7
8
9
10
11
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>

${errorMsg}

</body>
</html>

拦截器

SpringMVC的拦截器用于对处理器进行预处理和后处理,类似Servlet的过滤器 Filter

是AOP的体现

拦截器链

将拦截器按一定的顺序联结成一条链,按顺序调用

与过滤器的区别

过滤器是Servlet规范中的一部分,任何java web工程都可以用;拦截器是Spring MVC框架的

过滤器在url-pattern中配置了”/*”后,可以对所有要访问的资源拦截;拦截器只会拦截访问的控制器方法,不会拦截jsp、html等

使用步骤

  1. 编写拦截器,实现HandlerInterceptor接口
  2. 配置拦截器

控制器

1
2
3
4
5
6
7
8
9
10
11
@Controller
@RequestMapping("/user")
public class UserController {

@RequestMapping("/testInterceptor")
public String testInterceptor(){
System.out.println("testInterceptor执行了...");
return "success";
}

}

自定义拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MyInterceptor1 implements HandlerInterceptor{

// 预处理,controller方法执行前
// return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
// return false 不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1执行了...前");
// 也可以请求转发
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}

// 后处理方法,controller方法执行后,success.jsp执行之前
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1执行了...后");
}

// success.jsp页面执行后,该方法会执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor1执行了...最后");
}

}

配置

springmvc.xml中

1
2
3
4
5
6
7
8
9
10
11
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/user/*"/>
<!--不要拦截的方法
<mvc:exclude-mapping path=""/> -->
<!--配置拦截器对象-->
<bean class="cn.itcast.controller.cn.itcast.interceptor.MyInterceptor1" />
</mvc:interceptor>
</mvc:interceptors>

要拦截的方法和不要拦截的方法配置一个就可以了

这样配置拦截器后,测试输出为

1
2
3
4
5
MyInterceptor1执行了...前
testInterceptor执行了
MyInterceptor1执行了...后
success.jsp执行了
MyInterceptor1执行了...最后

2个拦截器

拦截器代码和第一个一样

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<mvc:interceptors>
<!--配置拦截器-->
<mvc:interceptor>
<mvc:mapping path="/user/*"/>
<!--配置拦截器对象-->
<bean class="cn.itcast.controller.cn.itcast.interceptor.MyInterceptor1" />
</mvc:interceptor>

<!--配置第二个拦截器-->
<mvc:interceptor>
<!--拦截所有方法-->
<mvc:mapping path="/**"/>
<!--配置拦截器对象-->
<bean class="cn.itcast.controller.cn.itcast.interceptor.MyInterceptor2" />
</mvc:interceptor>
</mvc:interceptors>

输出

1
2
3
4
5
6
7
8
MyInterceptor1执行了...前1
MyInterceptor1执行了...前2
testInterceptor执行了
MyInterceptor1执行了...后2
MyInterceptor1执行了...后1
success.jsp执行了
MyInterceptor1执行了...最后2
MyInterceptor1执行了...最后1