1 拦截器
1.1 定义
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
1.2 拦截器定义
实现HandlerInterceptor接口,如下:
public class HandlerInterceptor1 implements HandlerInterceptor {
/**
*
* controller执行前调用此方法
*
* 返回true表示继续执行,返回false中止执行
*
* 这里可以加入登录校验、权限拦截等
*
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
// TODO Auto-generated method stub
return false;
}
/**
*
* controller执行后但未返回视图前调用此方法
*
* 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
*
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
/**
*
* controller执行后且视图返回后调用此方法
*
* 这里可得到执行controller时的异常信息
*
* 这里可记录操作日志,资源清理等
*
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
}
1.3 拦截器配置
1.3.1 针对某种mapping配置拦截器
<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" />
1.3.2 针对所有mapping配置全局拦截器
<!--拦截器 -->
<mvc:interceptors>
<!--多个拦截器,顺序执行 -->
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.sihai.springmvc.filter.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.sihai.springmvc.filter.HandlerInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
1.4 正常流程测试
1.4.1 代码:
定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2,每个拦截器的preHandler方法都返回true。
1.4.2 运行流程
HandlerInterceptor1..preHandle..
HandlerInterceptor2..preHandle..
HandlerInterceptor2..postHandle..
HandlerInterceptor1..postHandle..
HandlerInterceptor2..afterCompletion..
HandlerInterceptor1..afterCompletion..
1.5 中断流程测试
1.5.1 代码:
定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2。
1.5.2 运行流程
HandlerInterceptor1的preHandler方法返回false,HandlerInterceptor2返回true,运行流程如下:
HandlerInterceptor1..preHandle..
从日志看出第一个拦截器的preHandler方法返回false后第一个拦截器只执行了preHandler方法,其它两个方法没有执行,第二个拦截器的所有方法不执行,且controller也不执行了。
HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回false,运行流程如下:
HandlerInterceptor1..preHandle..
HandlerInterceptor2..preHandle..
HandlerInterceptor1..afterCompletion..
从日志看出第二个拦截器的preHandler方法返回false后第一个拦截器的postHandler没有执行,第二个拦截器的postHandler和afterCompletion没有执行,且controller也不执行了。
总结:
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用
postHandler在拦截器链内所有拦截器返成功调用
afterCompletion只有preHandle返回true才调用
1.6 拦截器应用
1.6.1 用户身份认证
public class LoginInterceptorimplements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
// 如果是登录页面则放行
if (request.getRequestURI().indexOf("login.action") >= 0) {
return true;
}
HttpSession session = request.getSession();
// 如果用户已登录也放行
if (session.getAttribute("user") != null) {
return true;
}
// 用户没有登录挑战到登录页面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
}
}
1.6.2 用户登陆controller
// 登陆页面
@RequestMapping("/login")
public String login(Model model) throws Exception {
return "login";
}
// 登陆提交
// userid:用户账号,pwd:密码
@RequestMapping("/loginsubmit")
public String loginsubmit(HttpSession session, String userid, String pwd) throws Exception {
// 向session记录用户身份信息
session.setAttribute("activeUser", userid);
return "redirect:item/queryItem.action";
}
// 退出
@RequestMapping("/logout")
public String logout(HttpSession session) throws Exception {
// session过期
session.invalidate();
return "redirect:item/queryItem.action";
}