补充:
interceptor 的执行顺序大致为:
1.请求到达 DispatcherServlet
2.DispatcherServlet 发送至 Interceptor ,执行 preHandle
3.请求达到 Controller,返回视图前执行 postHandle
4.请求结束后,postHandle 执行
先看下 刚刚拿三个重写的方法(特征已经说了 这里不说)
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }
第一个是preHandle 他有三个参数 ,都是我们学过最基本的 请求、响应,至于第三个 handler ,我也不知道 我百度了一下:
handler,是指controller的@Controller注解下的"完整"方法名, 是包含exception等字段信息的. emmm...用的不多
其实呢 preHandle这个方法 主要还是用来判断用户有无权限 或 参数是否正确,这个方法是用的最多的 ,因为每一次请求都要结果他: 下面演示 不合格拦截后跳转到index(或者其他页面):
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String Parameter = request.getParameter("init"); //如果携带参数 init 且 init = yes 的话 那么就放行 不然就转发(或者其他)到index(视图解析器已配置) if ("yes".equals(Parameter)){ return true; }else{ request.getRequestDispatcher("/index.jsp").forward(request,response); } return false; }
第二个方法 的参数 是第一个一样的 再加一个 ModelAndView ,如果你控制器的方法里 有modelandview 你完全可以吧你携带出去的数据 在这里做更改,但是没必要 ,因为你本来就要带出去还改他干嘛...
测试一下:
控制器方法:(modelandview (这里是分离的 我懒得写,都一样的)已携带 data)
@RequestMapping("/show") public String show(Model model){ model.addAttribute("data","成功返回 未被拦截!"); //已携带data return "TestJSP"; }
拦截器postHandle方法:
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { //控制器方法那里携带了参数 data ,这里替换掉。 modelAndView.addObject("data","成功执行 已替换参数 未拦截!"); }
允许结果:
第三个方法没什么好说的 ,前两个是请求和响应,第三个是 Handler 第四个是异常 这个几乎不怎么用。。。。
暂缺
多拦截器
我们在声明拦截器的时候 是用 <mvc:interceptors> 然后下面的 <mvc:interceptor> 标签来声明,一个拦截器可以设置拦截指定的控制器 网址。
因为可以配置多个拦截器 所以呢,如果我配置了多个拦截器 而且 这些拦截器拦截的网址一样的话 那么他有个过滤器执行的先后顺序:
比如现在我有两个拦截器 两个一个 MyHandlerInterceptor 一个是 MyHandlerInterceptor2 ,那么使他们都拦截同一个网址 show :
拦截器:
package com.bihu; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyHandlerInterceptor implements HandlerInterceptor { @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 { System.out.println("我是拦截器的postHandle方法 我执行了!"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("我是拦截器的afterCompletion方法 我执行了!"); } }
拦截器2:
package com.bihu; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyHandlerInterceptor2 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("我是拦截器的preHandle2方法 我执行了!"); return true; //测试先后顺序 放行 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("我是拦截器的postHandle2方法 我执行了!"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("我是拦截器的afterCompletion2方法 我执行了!"); } }
然后 拦截器配置(声明):
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.bihu.MyHandlerInterceptor"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.bihu.MyHandlerInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
注意啊 连个拦截器都拦截全部的请求(url)
然后我们直接测试一下 看下打印结果:
我是拦截器的preHandle方法 我执行了!
我是拦截器的preHandle2方法 我执行了!
我是拦截器的postHandle2方法 我执行了!
我是拦截器的postHandle方法 我执行了!
我是拦截器的afterCompletion2方法 我执行了!
我是拦截器的afterCompletion方法 我执行了!
可以看到 先执行了 :
拦截器的 pre ==》拦截器2的pre ===》
拦截器2的post ==》 拦截器的 post ==》
拦截器2 的 after ==》拦截器的 after ==》结束
其实我们还记得firter过滤器吗,他执行的顺序是在web.xml中定义的顺序,那么其实springmvc也是,至于为什么post方法哪里 拦截器2先执行 是因为 类似于弹栈 (个人觉得 总之顺序就是这样),
我把他们配置的顺序调换一下:
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.bihu.MyHandlerInterceptor2"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.bihu.MyHandlerInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
执行结果:
我是拦截器的preHandle2方法 我执行了!
我是拦截器的preHandle方法 我执行了!
我是拦截器的postHandle方法 我执行了!
我是拦截器的postHandle2方法 我执行了!
我是拦截器的afterCompletion方法 我执行了!
我是拦截器的afterCompletion2方法 我执行了!
呐 总之顺序就是这样
摘抄CSDN博主 这瓜保熟么 链接:https://blog.csdn.net/luzhensmart/article/details/86702671
那么拦截器和过滤器有什么区别:
(1)Filter需要在web.xml中配置,依赖于Servlet;
(2)Interceptor需要在SpringMVC中配置,依赖于框架;
(3)Filter的执行顺序在Interceptor之前,具体的流程见下图;
两者的本质区别:拦截器(Interceptor)是基于Java的反射机制,而过滤器(Filter)是基于函数回调。从灵活性上说拦截器功能更强大些,Filter能做的事情,都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类),太细的话,还是建议用interceptor。不过还是根据不同情况选择合适的。