springMVC中的连接器相当于struts2中的filter,实现的作用一样,这以登录为例来说明拦截器
一:定义拦截器
该拦截器类要实现HandlerInterceptor接口,该接口定义了三个方法:
public class LoginInterceptor implements HandlerInterceptor{
//进入handler方法之前执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//获取请求的url
String url = request.getRequestURI();
//判断rui是否为公开
if (url.indexOf("login.action") > 0){
return true;
}
HttpSession session = request.getSession();
String username = (String)session.getAttribute("username");
if (username != null){
return true;
}
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);;
//true表示放行
return false;
}
//进入handler方法之后返回modelAndView之前执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
//进入handler完成执行此方法
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
preHandle()
- 执行时间:进入handler方法之前执行
- 应用环境:身份认证,身份授权
- 举例说明:登录系统时,如果用户没登录,就需要此方法拦截,不让用户登录系统
- 特殊情况:用户登录时,输入用户名和密码时要跳转页面,此时session中也还没有用户信息,所以此时还是无法登录;我们经常逛的淘宝,就算我们没登录也可以看到商品主页面;针对以上两种情况,我们就需要设置公开地址(即不用用户登录也能进入系统的地址)
- 返回值说明:返回true:放行,继续往下执行;返回false,进行拦截,不能继续往下执行
postHandle()
- 执行时间:进入handler方法之后,返回modelAndView之前执行
- 应用环境:将公用的模型数据(如菜单导航)在这里传到视图,也可统一指定视图
- 举例说明:系统的菜单导航栏应用
afterCompletion
- 执行时间:handler执行完成后执行
- 应用环境:统一异常处理,统一日志处理
二:拦截器配置
springmvc拦截器是针对HandlerMapping进行拦截设置,只有经过HandlerMapping映射成功的handler才能使用该拦截器
1.针对单个HandlerMapping配置,即针对单个的controller设置
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="handlerInterceptor1"/>
<ref bean="handlerInterceptor2"/>
</list>
</property>
</bean>
<bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>
<bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
一个HandlerMapping可配置多个拦截器(一般不使用此种方法)
2.类似全局的拦截器
springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中
<!--拦截器 -->
<mvc:interceptors>
<!--多个拦截器,顺序执行 -->
<!-- 登陆认证拦截器 -->
<mvc:interceptor>
<!-- **表示所有url包括子url路径 -->
<mvc:mapping path="/**"/>
<bean class="cn.itcast.ssm.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1"></bean>
</mvc:interceptor>
</mvc:interceptors>
这样以来,每次请求handler时,都先执行拦截器
三:多个拦截器的执行顺序(按第一个配置来说)
1.拦截器1放行,拦截器2放行
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle
HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion
- preHandle方法按顺序执行,postHandle和afterCompletion按拦截器配置的逆向顺序执行
2.拦截器1放行,拦截器2不放行
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion
- 拦截器1放行,拦截器2 preHandle才会执行
- 拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion不会执行
- 只要有一个拦截器不放行,postHandle不会执行
3.拦截器1不放行,拦截器2不放行
HandlerInterceptor1...preHandle
- 拦截器1 preHandle不放行,postHandle和afterCompletion不会执行
- 拦截器1 preHandle不放行,拦截器2不执行
综上:
- 统一日志处理拦截器,需要该 拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置
- 登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)