SpringMVC 中的 Interceptor 拦截器是非常重要和相当有用的,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。其拦截的时间点在“处理器映射器根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器执行处理器之前”。当然,在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链,并返回给了中央调度器。
工作流程
package com.liuhaiyang.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpSession;
@Controller
public class MyController {
@RequestMapping(value = "/some.do")
public ModelAndView doforward(HttpSession session, String name, Integer age){
System.out.println("执行了MyController的dosome方法");
//添加一个临时数据
session.setAttribute("attr","在controller中增加一个临时数据");
ModelAndView mv=new ModelAndView();
mv.addObject("name",name);
mv.addObject("age",age);
mv.setViewName("show");
return mv;
}
}
package com.liuhaiyang.handler;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
/**
* 拦截器
*/
public class Myhandler implements HandlerInterceptor {
/**
* preHandle:预先处理请求的方法 。相当于总开关 参数:Object handler:被拦截的控制器对象(Mycontroller)
* 返回值:Boolean 当为真时,请求正确,可以被Controller处理,程序正常执行。
* 当为假时,请求不能被处理,控制器方法不会执行。请求到此截止。
* 特点:1.预处理方法的执行时间:在控制器方法之前先执行的. 2.可以对请求做处理,可以做登陆检查,全限的判断,统计数据等等
* 3.决定请求是否被执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("=====MyHandler拦截器的preHandler====");
// request.getRequestDispatcher("/tips.jsp").forward(request,response);
return true;
}
/**
* postHandler:后处理方法 参数:Object handler:被拦截的控制器对象(MyController)
* ModelAndView mv:控制器方法的返回值(请求的执行结果)
* 特点:1.在控制器方法之后执行的。 2.能获取到控制器方法的执行结果。可以修改原来的执行结果
* 可以修改数据,也可以修改视图。 3.可以做对请求的二次处理
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView mv) throws Exception {
System.out.println("=====MyHandler拦截器的postHandler====");
if (mv!=null){
mv.addObject("mydate",new Date());
mv.setViewName("other");
}
}
/**
* afterCompletion:最后执行的方法 参数:Object handler:被拦截的控制器对象(MyController) Exception ex:异常对象
* 特点:1.在请求处理完成后执行的,请求处理完成的标志 是视图处理完成,对试图执行forward操作后
* 2.可以做程序最后要做的工作,释放内存,清理临时变量
* 3.方法的执行条件:1)当前的拦截器它的preHandler方法必须执行。 2)preHandler必须返回true
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("=====MyHandler拦截器的afterCompletion====");
HttpSession session=request.getSession();
Object obj=session.getAttribute("attr");
System.out.println("attr==="+obj);
//删除数据
session.removeAttribute("attr");
//检查
obj=session.getAttribute("attr");
System.out.println("删除后,检查是还存在,attr="+obj);
}
}
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
1
springmvc
*.do
characterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
forceRequestEncoding
true
forceResponseEncoding
true
characterEncodingFilter
/*
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
springmvc
拦截器操作
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
拦截器做出的输出,显示request作用域中的数据
name数据:<%=request.getAttribute("name")%>
age数据:${age}
date时间数据:${mydate}
当拦截器类中的 preHandle 方法返回 true 时,请求的执行顺序:用户发起some.do → preHandle → 控制器的doSome方法 → postHandle → afterCompletion。
当拦截器类中的 preHandle 方法返回 false 时,请求仅仅只会执行 preHandle 方法。
工作流程
package com.liuhaiyang.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpSession;
@Controller
public class MyController {
@RequestMapping(value = "/some.do")
public ModelAndView doforward(HttpSession session, String name, Integer age){
System.out.println("执行了MyController的dosome方法");
ModelAndView mv=new ModelAndView();
mv.addObject("name",name);
mv.addObject("age",age);
mv.setViewName("show");
return mv;
}
}
package com.liuhaiyang.handler;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
public class Myhandler implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("=====MyHandler11111拦截器的preHandler====");
// request.getRequestDispatcher("/tips.jsp").forward(request,response);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView mv) throws Exception {
System.out.println("=====MyHandler11111拦截器的postHandler====");
if (mv!=null){
mv.addObject("mydate",new Date());
mv.setViewName("other");
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("=====MyHandler11111拦截器的afterCompletion====");
HttpSession session=request.getSession();
Object obj=session.getAttribute("attr");
System.out.println("attr==="+obj);
//删除数据
session.removeAttribute("attr");
//检查
obj=session.getAttribute("attr");
System.out.println("删除后,检查是还存在,attr="+obj);
}
}
package com.liuhaiyang.handler;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
public class Myhandler2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("=====MyHandler22222拦截器的preHandler====");
// request.getRequestDispatcher("/tips.jsp").forward(request,response);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView mv) throws Exception {
System.out.println("=====MyHandler22222拦截器的postHandler====");
if (mv!=null){
mv.addObject("mydate",new Date());
mv.setViewName("other");
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("=====MyHandler22222拦截器的afterCompletion====");
HttpSession session=request.getSession();
Object obj=session.getAttribute("attr");
System.out.println("attr==="+obj);
//删除数据
session.removeAttribute("attr");
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
多个拦截器
拦截器操作
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
拦截器做出的输出,显示request作用域中的数据
name数据:<%=request.getAttribute("name")%>
age数据:${age}
date时间数据:${mydate}
用户发起some.do → 拦截器1的 preHandle 方法 → 拦截器2的 preHandle 方法 → 控制器的doSome方法 → 拦截器2的postHandle方法 → 拦截器1的postHandle方法 → 拦截器2的 afterCompletion 方法 → 拦截器1的 afterCompletion 方法。
当第一个拦截器返回 true,第二个拦截器返回 false时,请求的执行顺序是这样的:
用户发起some.do → 拦截器1的 preHandle 方法 → 拦截器2的 preHandle 方法 → 拦截器1的 afterCompletion 方法。
当第一个拦截器返回 false,第二个拦截器返回值无论是 true 还是 false ,请求的执行顺序都只能是这样的:
用户发起some.do → 拦截器1的 preHandle 方法。因为拦截器1的 preHandle 方法返回 false之后,直接就切断了请求的执行,后面都不会再执行其他内容了。
package com.liuhaiyang.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpSession;
@Controller
public class MyController {
@RequestMapping(value = "/some.do")
public ModelAndView doforward(HttpSession session, String name, Integer age){
System.out.println("执行了MyController的dosome方法");
//添加一个临时数据
session.setAttribute("attr","在controller中增加一个临时数据");
ModelAndView mv=new ModelAndView();
mv.addObject("name",name);
mv.addObject("age",age);
mv.setViewName("show");
return mv;
}
}
package com.liuhaiyang.handler;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
public class Myhandler implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("=====MyHandler11111拦截器的preHandler====");
String username="";
//获取登录信息
Object attr= request.getSession().getAttribute("username");
if (attr!=null){
username=(String) attr;
}
if ("zhangsan".equals(username)){
return true;
}else {
request.getRequestDispatcher("/tips.jsp").forward(request,response);
return false;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView mv) throws Exception {
System.out.println("=====MyHandler11111拦截器的postHandler====");
if (mv!=null){
mv.addObject("mydate",new Date());
mv.setViewName("other");
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("=====MyHandler11111拦截器的afterCompletion====");
HttpSession session=request.getSession();
Object obj=session.getAttribute("attr");
System.out.println("attr==="+obj);
//删除数据
session.removeAttribute("attr");
//检查
obj=session.getAttribute("attr");
System.out.println("删除后,检查是还存在,attr="+obj);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
拦截器小例子
拦截器操作
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
拦截器做出的输出,显示request作用域中的数据
name数据:<%=request.getAttribute("name")%>
age数据:${age}
date时间数据:${mydate}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
登录
登陆操作<%
session.setAttribute("username","zhangsan");
%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
退出操作
退出系统!!!!<%
session.removeAttribute("username");
%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
tips.jsp 系统不允许访问!!!
首先通过 login.jsp 页面发起请求(获取会话作用域对象,此时的用户名只能是 zhangsan);之后通过 index.jsp 首页,发起 some.do 请求进行登录,如果输入的用户名是 zhangsan,则会转到正确的页面:result.jsp;如果输入了其他用户名,则会通过请求转发,直接转到非用户无法登录的页面:tips.jsp。最后可以通过登出页面(logout.jsp),将自己的用户名信息进行删除。
拦截器和过滤器的差别:
1.拦截器是springmvc框架中的对象。过滤器是servlet中的对象。
2.拦截器对象是由框架容器创建的。过滤器对象是由tomcat创建的。
2.拦截器侧重于对请求做判断处理的,可以截断请求。过滤器侧重于对request、response对象的属性、参数设置值的。
4.拦截器的执行时间有三个(控制器方法之前、控制器方法之后、请求完成之后)。过滤器执行时间只在请求之前。
5.拦截器是对controller、动态资源进行拦截的。过滤器可以过滤所以请求(动态、静态)。
6.拦截器和过滤器一起执行:先执行过滤器,后面是中央调度器,再后面是拦截器,最后才是控制器方法。