SpringMVC 中的 Interceptor 拦截器作用是拦截指定的用户请求(对请求作判断处理),并进行相应的预处理与后处理,需要实现 HandlerInterceptor 接口;拦截器是全局的,一个项目中可以有零个或多个拦截器,可以对多个Controller进行拦截
注意和过滤器的区别:过滤器是用户过滤请求参数,设置编码字符集等工作;拦截器是用于拦截用户请求,做请求的判断处理的
拦截器常用于:用户登陆处理,权限检查,记录日志
使用步骤:
1. 定义类实现 HandlerInterceptor
接口
2. 在springmvc配置文件中声明拦截器,让框架知道拦截器的存在
拦截器执行时间:
1. 在controller类中方法执行之前(请求处理之前)执行拦截器
2. 在控制器方法执行后也可以执行拦截器
3. 在请求处理完成后也会执行拦截器
实现步骤:
@Controller
public class Mycontroller {
@RequestMapping(value = "/some.do")
public ModelAndView doSome(String name,Integer age){
System.out.println("我是控制器方法");
ModelAndView mv=new ModelAndView();
mv.addObject("msg",name);
mv.addObject("fun",age);
mv.setViewName("show");
return mv;
}
}
HandlerInterceptor
接口public class MyInterceptor implements HandlerInterceptor {//拦截器类:拦截用户请求
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器的preHandle执行。。。");
//给浏览器一个返回结果
request.getRequestDispatcher("/tips.jsp").forward(request,response);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器的postHandle执行。。。");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器的afterCompletion执行。。。");
}
}
preHandle
:预处理方法
参数:Object handler
,被拦截的对象
返回值boolean:true
:false
:
特点:
1. 方法在控制器方法前执行,用户的请求首先到达此方法
2. 在这个方法中可以获取请求信息,验证请求是都符合要求,可以验证用户是否登陆,验证用户是否有权限访问某个连接请求(url);验证成功===>可以放行请求,此时控制器方法才能执行,验证失败===>可以阶段请求,请求不能被处理
postHandle
:后处理方法
参数:ModelAndView modelAndView
,处理器方法的返回值
特点:
1. 在处理器方法之后执行
2. 能够获取处理器方法的返回值modelAndView
,可以修改modelAndView
中的数据和视图,可以影响最后的执行结果
3. 主要时对原来的执行结果做二次修正
afterCompletion
:最后执行的方法
参数:Exception ex
,程序中发生的异常
特点:
1. 在请求处理完成后执行的,框架中规定时当你的视图处理完成后(对视图执行了forward
),就认为请求处理完成
2. 一般做资源回收的工作,程序请求过程中创建了一些对象,在这里可以将其删除,把占用的内存回收
执行的顺序:preHandle–>控制器方法–>postHandle–>afterCompletion
preHandle返回false,再来一遍
可以看到,当postHandle
返回false
时,请求会被拦截,项目只执行了postHandle
方法,所以我们要在postHandle
中写判断的逻辑语句,对请求进行拦截;可以把拦截器看作是多个Controller中公用的功能,集中到拦截器统一处理,使用的aop的思想
我们可以在postHandle中试着修改返回值modelAndView
(记得把返回值改回true和把转发语句去掉 )
//对原来的方法进行调整
if(modelAndView != null){
//修改数据
modelAndView.addObject("mydate",new Date());
//修改视图
modelAndView.setViewName("other");
}
我们用这个方法计算整个拦截器执行的时间
首先设置一个全局变量保存执行时间private long btime=0;
postHandle
中给btime赋值当前时间btime=System.currentTimeMillis();
afterCompletion
设置结束的当前时间long etime=System.currentTimeMillis();
返回true:再创建一个拦截器类,然后在配置文件中再声明多一个拦截器,要注意,这里使用的是ArrayList来保存拦截器的声明,有顺序,先声明的先执行;两个返回值都为true
我们可以看到,先执行第一个拦截器,再执行第二个拦截器,然后执行控制器方法,然后反过来执行拦截器
Filter
接口的对象, 拦截器是实现HandlerInterceptor
request
,response
的参数,属性的,侧重对数据过滤的。DispatcherServlet
接收, 这个请求不会执行拦截器内容简单使用拦截器模拟验证登陆用户是否有权限访问系统,这里只展示新增的代码,其他代码和配置和前面一致
<%
session.setAttribute("name","zs");
%>
<%
session.removeAttribute("name");
%>
public class MyInterceptor implements HandlerInterceptor {//拦截器类:拦截用户请求
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//验证登陆用户的信息,正确返回true,错误返回false
System.out.println("1111-拦截器的preHandle执行。。。");
String loginName="";
//从session获取name的值
Object attr=request.getSession().getAttribute("name");
if(attr != null){
loginName= (String) attr;
}
//判断登陆的账号是否符合要求
if(!"zs".equals(loginName)){
//不能访问系统
//给用户提示
request.getRequestDispatcher("/tips.jsp").forward(request,response);
return false;
}
//zs登陆
return true;
}
}
条条:该学习笔记是记录了我的学习过程,学习自动力节点王鹤老师,有不对的地方欢迎指出