2017/12/13更新
关于拦截器mvc:mapping path里”/”和“*”的写法,参考这篇文章
http://blog.youkuaiyun.com/u014520797/article/details/52893474
简言之
- /* 只能拦截一层目录
- /**所有请求
- xxx/*xxx目录下
- /无法拦截
2017/12/03更新
关于IP拦截的的ipfilter注解的使用,在remmopj中有少许改动
http://www.cnblogs.com/huanmin/p/7810467.html
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
1,拦截器定义
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
}
}
2,拦截器配置
2.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"/>
2.2,针对所有mapping配置全局拦截器
<!--拦截器 -->
<mvc:interceptors>
<!--多个拦截器,顺序执行 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.itcast.springmvc.filter.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.itcast.springmvc.filter.HandlerInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
3,测试
3.1,每个拦截器都返回ture的情况下
HandlerInterceptor1..preHandle..
HandlerInterceptor2..preHandle..
HandlerInterceptor2..postHandle..
HandlerInterceptor1..postHandle..
HandlerInterceptor2..afterCompletion..
HandlerInterceptor1..afterCompletion..
3.2,HandlerInterceptor1的preHandler方法返回false,HandlerInterceptor2返回true
HandlerInterceptor1..preHandle..
从日志看出第一个拦截器的preHandler方法返回false后第一个拦截器只执行了preHandler方法,其它两个方法没有执行,第二个拦截器的所有方法不执行,且controller也不执行了。
3.3,HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回false
HandlerInterceptor1..preHandle..
HandlerInterceptor2..preHandle..
HandlerInterceptor1..afterCompletion..
从日志看出第二个拦截器的preHandler方法返回false后第一个拦截器的postHandler没有执行,第二个拦截器的postHandler和afterCompletion没有执行,且controller也不执行了。
总结:
- preHandle按拦截器定义顺序调用
- postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用
postHandler在拦截器链内所有拦截器返成功调用
- afterCompletion只有preHandle返回true才调用
4,拦截器应用
4,1,处理流程
- 有一个登录页面,需要写一个controller访问页面
- 登录页面有一提交表单的动作。需要在controller中处理
- a) 判断用户名密码是否正确
- b) 如果正确 想session中写入用户信息
- c) 返回登录成功,或者跳转到商品列表
- 拦截器
- a) 拦截用户请求,判断用户是否登录
- b) 如果用户已经登录。放行
- c) 如果用户未登录,跳转到登录页面。
4.2,用户身份认证
Public class LoginInterceptor implements 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;
}
}
4.3,用户登陆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";
}