SpringMVC中的Interceptor拦截器是非常重要和相当有用的,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。拦截器是全局的,可以对多个Controller做拦截。一个项目中可以有0个或多个拦截器, 他们在一起拦截用户的请求。拦截器常用在:用户登录处理,权限检查, 记录日志。
1、一个拦截器的执行
实现步骤:
1、创建Controller类
2、创建一个普通类
1)实现HandleInterceptor接口
2)实现接口中的三个方法
3、创建show页面
4、创建Springmvc的配置文件
1)组件扫描器,扫描@Controller注解
2)声明拦截器,并指定拦截的请求uri地址
在创建普通类实现HandleInterceptor接口时,三个方法的详细讲解:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器方法preHandle()执行");
return true;
}
preHandle: 预处理方法
参数:
Object handler :被拦截的控制器对象myController
返回值是Boolean:
1、true:请求通过了拦截器的验证,可以执行处理器方法
2、false:就是请求没有通过拦截器的验证,不能执行处理器方法
特点:
1、在控制器方法执行(myController的方法)之前先执行的 用户的请求首先到达此方法
2、在这个方法中可以获取请求的信息,验证请求是否符合要求 可以验证用户是否登录,验证用户是否有权限访问某个链接地址(url) 。
如果验证失败,可以截断请求,请求不能被处理 。
如果验证成功,可以放行请求,此时控制器方法才能执行。
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
time = System.currentTimeMillis();
if(modelAndView !=null){
modelAndView.addObject("mydate",new Date());
modelAndView.setViewName("other");
}
System.out.println("拦截器方法postHandle()执行");
}
postHandle :后处理方法
参数:
Object handler: 被拦截的处理对象myController
ModelAndView :modelAndView:处理器方法的返回值
特点:
1、在处理器方法之后执行的(myController.dosome())
2、可以获取处理器方法的返回值ModelAndView,可以修改ModelAndView中的数据和视图,可以影响到最后执行结果。
3、它主要功能:就是对原来的执行结果执行第二次修正
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("postHandle到afterCompletion方法的执行时间:"+(System.currentTimeMillis()-time));
System.out.println("拦截器的afterCompletion()执行了");
}
afterCompletion:最后执行的方法
参数:
Object handler:被拦截的控制器对象myController
Exception ex:程序发生的异常
特点:
1、在请求处理完成后执行的,框架中规定是当你的视图处理完成后,对视图执行了forward就认为请求处理完成
2、一般做资源回收的工作的,在程序请求的过程中创建了一些对象,在这里可以删除、回收
创建Springmvc的配置文件:
声明拦截器:拦截器可以有0个或者多个
声明第一个拦截器 一个interceptor就是一个拦截器
mapping path="" 指定拦截的请求url地址
path:就是uri地址,可以使用通配符 **
**:表示任意字符,文件或者多级目录和目录中的文件 /user/**:这个以user开头就会拦截
/user:前面的/是根目录
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="cn.com.Ycy.Contrller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀名:视图文件的路径-->
<property name="prefix" value="/WEB-INF/"/>
<!-- 后缀名:视图文件的扩展名 -->
<property name="suffix" value=".jsp"/>
</bean>
<!-- 声明拦截器:拦截器可以有0个或者多个 -->
<mvc:interceptors>
<!-- 声明第一个拦截器 一个interceptor就是一个拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<bean class="cn.com.Ycy.handler.myInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
代码演示:
页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta http-equiv="Content-Type" content="textml; charset=UTF-8">
<title>Title</title>
</head>
<body>
<p>一个拦截器</p>
<form action="user/some.do" method="post">
姓名:<input type="text" name="name"><br/>
年龄:<input type="text" name="age"><br/>
<input type="submit" value="提交请求">
</form>
</body>
</html>
Controller类 :
@RequestMapping(value = "/user")
@Controller
public class myController {
@RequestMapping(value = "/some.do")
public ModelAndView dosome(String name,String age) {
System.out.println("dosome方法执行");
ModelAndView mv = new ModelAndView();
mv.addObject("myname",name);
mv.addObject("myage",age);
mv.setViewName("show");
return mv;
}
}
拦截器类 :
public class myInterceptor implements HandlerInterceptor {
private long time;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器方法preHandle()执行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
time = System.currentTimeMillis();
if(modelAndView !=null){
modelAndView.addObject("mydate",new Date());
modelAndView.setViewName("other");
}
System.out.println("拦截器方法postHandle()执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("postHandle到afterCompletion方法的执行时间:"+(System.currentTimeMillis()-time));
System.out.println("拦截器的afterCompletion()执行了");
}
}
拦截器中方法与处理器方法的执行顺序如下图 :
2、多个拦截器的执行
当有多个拦截器时,形成拦截器链。拦截器链的执行顺序,与其注册顺序一致。需要再 次强调一点的是,当某一个拦截器的 preHandle()方法返回 true 并被执行到时,会向一个专 门的方法栈中放入该拦截器的 afterCompletion()方法。
多个拦截器的注册与执行:
输出结果:
多个拦截器中方法与处理器方法的执行顺序如下图: