一、拦截器
1.1 概述
- SpringMVC框架中的拦截器用于对处理器进行 预处理 和 后处理 的技术。
- 可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链中的拦截器会按着定义的顺序执行。
- 拦截器和过滤器的功能比较类似,有如下区别:
- 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
- 拦截器是 SpringMVC 框架独有的。
- 过滤器配置了 /*,可以拦截任何资源。
- 拦截器只会对控制器中的方法进行拦截。
- 拦截器也是AOP思想的一种实现方式
- 想要自定义拦截器,需要实现 HandlerInterceptor 接口。
1.2 自定义拦截器步骤
-
创建类,实现 HandlerInterceptor 接口,重写需要的方法。
return true 放行,执行下一个拦截器。如果没有,执行 controller 中的方法
return false 不放行。public class MyInterceptor implements HandlerInterceptor { /** * 预处理,在controller方法执行前 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor执行了。。"); //成功放行 return true; //不放行 //request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response); //return false; } }
-
在 springmvc.xml 中配置拦截器类。
<!--配置拦截器--> <mvc:interceptors> <!--配置第一个拦截器--> <mvc:interceptor> <!--要拦截的方法--> <mvc:mapping path="/user/*"/> <!--不要拦截的方法--> <!--<mvc:exclude-mapping path=""/>--> <!--配置拦截器对象--> <bean class="com.itheima.interceptor.MyInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
注:拦截的方法和不拦截的方法配置选择其一。
演示如下:
工程目录:
Controller:
@Controller
@RequestMapping(path = "/user")
public class UserController {
@RequestMapping(path = "/testInterceptor")
public String testInterceptor(){
System.out.println("testInterceptor方法执行了");
return "success";
}
}
演示页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>拦截器</h3>
<a href="user/testInterceptor">拦截器</a>
</body>
</html>
成功页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>执行成功</h3>
</body>
</html>
演示效果:
1.3 HandlerInterceptor接口中的方法
- preHandle 方法是controller方法 执行前拦截的方法
- 可以使用 request 或者 response 跳转到指定的页面
- return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
- return false不放行,不会执行controller中的方法。
- postHandle 是controller方法 执行后 执行的方法,在JSP视图执行前。
- 可以使用 request 或者 response 跳转到指定的页面
- 如果指定了跳转的页面,那么controller 方法跳转的页面将不会显示。
- afterCompletion 方法是在 JSP执行后执行
- request 或者 response不能再跳转页面了
代码演示:
public class MyInterceptor implements HandlerInterceptor {
/**
* 预处理,在controller方法执行前
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor执行了。。。前");
return true;
}
/**
* 后处理方法,controller方法执行后,success.jsp执行之前
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor执行了。。。后");
}
/**
* success.jsp执行后,该方法会执行
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor执行了。。。最后");
}
}
成功页面输出信息:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>执行成功</h3>
<%System.out.println("success.jsp");%>
</body>
</html>
演示结果:
1.4 配置多个拦截器
<!--配置拦截器-->
<mvc:interceptors>
<!--配置第一个拦截器-->
<mvc:interceptor>
<!--要拦截的方法-->
<mvc:mapping path="/user/*"/>
<!--不要拦截的方法-->
<!--<mvc:exclude-mapping path=""/>-->
<!--配置拦截器对象-->
<bean class="com.itheima.interceptor.MyInterceptor"></bean>
</mvc:interceptor>
<!--配置第二个拦截器-->
<mvc:interceptor>
<!--要拦截的方法-->
<mvc:mapping path="/user/*"/>
<!--不要拦截的方法-->
<!--<mvc:exclude-mapping path=""/>-->
<!--配置拦截器对象-->
<bean class="com.itheima.interceptor.MyInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截顺序是 根据配置里面的拦截顺序进行拦截,放行也是从最深处向外放行,具体图示如下:
演示效果如下:
二、异常处理
2.1 异常处理思路
Controller调用service,service调用dao,异常都是向上抛出的,最终有 DispatcherServlet 找异常处理器进行异常的处理。
2.2 异常处理实现
① 编写自定义异常类(做提示信息的)
② 编写异常处理器
③ 配置异常处理器(跳转到提示页面)
项目目录:
编写自定义异常类
public class SysException extends Exception{
// 存储提示信息的
private String message;
public SysException(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
自定义异常处理器
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;
}
}
配置异常处理器
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>
error.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${errorMsg}
</body>
</html>
controller:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testException")
public String testException() throws SysException{
System.out.println("testException执行了...");
try {
// 模拟异常
int a = 10/0;
} catch (Exception e) {
// 打印异常信息
e.printStackTrace();
// 抛出自定义异常信息
throw new SysException("查询所有用户出现错误了...");
}
return "success";
}
}