三. 多个拦截器之间的执行顺序
保留上面的配置,再创建两个拦截器 LoginInterceptor2 和LoginInterceptor3
三.一 创建 LoginInterceptor2 拦截器和 LoginInterceptor3 拦截器
LoginInterceptor2.java
package com.yjl.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class LoginInterceptor2 implements HandlerInterceptor{ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3){ System.out.println("控制器方法执行之后,视图解析器之后执行2"); } @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { System.out.println("控制器方法执行之后,视图解析器之前执行2"); } @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { System.out.println("会在控制器方法之前执行2"); return true; } }
LoginInterceptor3.java
package com.yjl.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class LoginInterceptor3 implements HandlerInterceptor{ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3){ System.out.println("控制器方法执行之后,视图解析器之后执行3"); } @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { System.out.println("控制器方法执行之后,视图解析器之前执行3"); } @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { System.out.println("会在控制器方法之前执行3"); return true; } }
三.二 后端 UserAction 保持不变
三.三 前端 login.jsp 代码保持不变
三.四 springmvc.xml 配置多个拦截器,注意顺序
<mvc:annotation-driven></mvc:annotation-driven> <!-- 配置拦截器 --> <mvc:interceptors> <!--可配置狐假虎威--> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.yjl.interceptor.LoginInterceptor1"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.yjl.interceptor.LoginInterceptor2"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.yjl.interceptor.LoginInterceptor3"></bean> </mvc:interceptor> </mvc:interceptors>
三.五 重启服务器,进行验证
执行 toLogin 方法时,
控制台打印输出:
输入用户名为 ‘两个蝴蝶飞’,密码为’abc’,错误密码时, 执行 login 方法时,控制台打印输出:
拦截器的执行顺序,是preHandler: 1,2,3, login方法, postHandle: 3,2,1,afterCompletion:3,2,1 的顺序执行的。
三.六 配置不同的拦截器的是否通过,验证preHandler() 返回false的情况。
1 .设置 LoginInterceptor1 通过, LoginInterceptor2 通过, LoginInterceptor3 不通过
即 LoginInterceptor1 中的 preHandler() 方法返回 true, LoginInterceptor2 中的 preHandler()方法返回true,
LoginInterceptor3 中的preHandler() 方法返回 false.
这个时候,执行 toLogin() 方法
控制台打印输出:
前端不显示任何东西, 没有返回到视图。
2 .设置 LoginInterceptor1 通过, LoginInterceptor2 不通过, LoginInterceptor3 不通过
即 LoginInterceptor1 中的 preHandler() 方法返回 true, LoginInterceptor2 中的 preHandler()方法返回false,
LoginInterceptor3 中的preHandler() 方法返回 false.
这个时候,执行 toLogin() 方法
控制台打印输出:
前端不显示任何东西, 没有返回到视图。
3 .设置 LoginInterceptor1 通过, LoginInterceptor2 不通过, LoginInterceptor3 通过
即 LoginInterceptor1 中的 preHandler() 方法返回 true, LoginInterceptor2 中的 preHandler()方法返回false,
LoginInterceptor3 中的preHandler() 方法返回 true.
这个时候,执行 toLogin() 方法
控制台打印输出:
前端不显示任何东西, 没有返回到视图。
2 不通过了,2以后的拦截器均不执行。
3 .设置 LoginInterceptor1 不通过, LoginInterceptor2 不通过, LoginInterceptor3 通过
即 LoginInterceptor1 中的 preHandler() 方法返回 false, LoginInterceptor2 中的 preHandler()方法返回false,
LoginInterceptor3 中的preHandler() 方法返回 true.
这个时候,执行 toLogin() 方法
控制台打印输出:
前端不显示任何东西, 没有返回到视图。
可知, 当 preHandler() 方法返回 false 时,只执行 preHandle()方法,不执行 控制器的请求方法 和拦截器以后的 postHandle 方法 和 afterCompletion()方法。
一般系统中所用的拦截器 ,日志拦截器,登录拦截器, 权限拦截器, 需要将日志拦截器设置为true,一定通过, 登录拦截器和权限拦截器 根据验证后的结果,如果登录了,就返回true,没有登录就返回false, 权限如果有就返回true,没有就返回false.且登录拦截器要放置在权限拦截器之前。
三.七 拦截器配置中的属性
在 mvc:interceptor 节点中,有三个元素。 mvc:mapping,mvc:exclude-mapping,bean 。
其中,顺序不能写颠倒, 一定要按照 mvc:mapping, mvc:exclude-mapping, bean 的顺序进行。
mvc:mapping, 表示拦截的路径, 如查询,添加,删除等功能, 一般要拦截的路径比较多。 /** 表示全部的路径。
<mvc:mapping path="/**"/>
mvc:exclude-mapping, 表示拦截的路径, 如 跳转到登录的页面, 登录, 注册的页面,注册,忘记密码 。 这个要写在拦截 mvc:mapping的下面,且必须要显示的写上 拦截的路径。
如不拦截跳转到登录的页面的功能。
<!--拦截所有的--> <mvc:mapping path="/**"/> <!--不拦截 /user/login 路径 。 记住,不写 项目名--> <mvc:exclude-mapping path="/user/toLogin"/>
当然,在拦截的时候,也可以拦截多个。 要写多个mvc:exclude-mapping, 而不是像Struts2那样加 , 分隔。
如拦截 跳转到登录,登录,注册,跳转到注册,忘记密码时
<mvc:mapping path="/**"/> <mvc:exclude-mapping path="/user/toLogin"/> <mvc:exclude-mapping path="/user/login"/> <mvc:exclude-mapping path="/user/toRegister"/> <mvc:exclude-mapping path="/user/register"/> <mvc:exclude-mapping path="/user/forgetPassword"/>
注意,在web.xml 配置的是REST 风格, 即 Dispatcher 的url-pattern 配置的是 /, 如果像以前那样,配置的是*.action,
那么这个配置就需要在后面添加.action 了。
<mvc:mapping path="/**"/> <mvc:exclude-mapping path="/user/toLogin.action"/> <mvc:exclude-mapping path="/user/login.action"/> <mvc:exclude-mapping path="/user/toRegister.action"/> <mvc:exclude-mapping path="/user/register.action"/> <mvc:exclude-mapping path="/user/forgetPassword.action"/>
要注意对应。
<mvc:mapping 也可以配置多个。
路径要写全路径, 不能够简写。 如 <mvc:exclude-mapping path="/toLogin"/> 这样是不行的。
支持后面 *的形式。 如
<mvc:exclude-mapping path="/user/toLo*"/> <mvc:exclude-mapping path="/user/log*"/>
/user/toLo1234, /user/toLogin, /user/logabc , /user/login 均是不拦截的。
前面的 * 也是可以的。
<mvc:exclude-mapping path="/*/toLo*"/> <mvc:exclude-mapping path="/*/log*"/>