springmvc拦截器

拦截器
拦截器的定义
类似于Filter,struts2有拦截器,是在Filter执行过程中进行的拦截。aop实现
拦截器的书写:

/**
* Created by Administrator on 2017/1/18.
* aop的表现
*/
public class MyInterceptor implements HandlerInterceptor {

//进入handler之前执行
//用于身份认证、身份授权
//比如身份认证,如果认证为通过表示用户没有登录,需要此方法拦截不再乡下执行
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {


//return false表示拦截,不向下执行
//return true 表示放行
return false;
}

//进入handler之后,返回modelAndView之前执行
//应用场景从modelAndView出发:将公用的模型数据(比如菜单的导航)在这里传到视图,也可以在这里面同一指定视图
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

}

//执行handler完成后
//应用场景:统一的异常处理,统一的日志处理
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

}
}


拦截器配置:
struts2中的拦截器是全局的,装载进拦截器链或者单个action特定拦截
springmvc中的拦截时针对HandlerMapping进行拦截设置

1、针对某种HandlerMapping的拦截器配置
如果在某个HandlerMapping中配置拦截,经过该HandlerMapping映射成功的handler最终使用该拦截器

<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"/>
...

一般不推荐使用

2、类似全局的拦截配置:
springmvc配置类似全局拦截器,springmvc的框架会将配置的类似全局的拦截器注入到每个HandlerMapping中。springmvc配置类似全局拦截器,springmvc的框架会将配置的类似全局的拦截器注入到每个HandlerMapping中。

<mvc:interceptors>
<!-- 多个拦截器,顺序执行 -->
<mvc:interceptor>
<!-- /** 表示所有的url包括子url路径,/*只拦截最根的url路径 -->
<mvc:mapping path="/**"/>
<bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>



拦截器测试
首先在拦截器1和拦截器2中定义logger用于观察:
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("HandlerInterceptor1...preHandle");

//return false表示拦截,不向下执行
//return true 表示放行
return false;
}

//进入handler之后,返回modelAndView之前执行
//应用场景从modelAndView出发:将公用的模型数据(比如菜单的导航)在这里传到视图,也可以在这里面同一指定视图
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1...postHandle");
}

//执行handler完成后
//应用场景:统一的异常处理,统一的日志处理
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("HandlerInterceptor1...afterCompletion");
}

测试1:
两个拦截器都放行
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle

HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle

HandlerInterceptor2...afterComplection
HandlerIncerceptor1...afterComplection
总结:
preHandle方法按顺序执行,postHandle和afterComplection逆序执行
拦截器1放行,拦截器2不放行
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion
总结:
拦截器1放行,拦截器2 preHandle才会执行
拦截器2 preHandle不放行,拦截器2 postHandle和afterComplection不会执行
只要有一个拦截器不放行,postHandle都方法不执行
拦截器1不放行,拦截器2也不放行
HandlerInterceptor1...preHandle
总结:
拦截器1 preHandle不放行,postHandle和afterCompletion不会执行
拦截器1 preHandle不放行,拦截器2不执行

小结:
根据测试结果,对拦截器应用。
比如同一日志处理结果,需要在preHandle一定要放行,且位于拦截器链的第一个位置。
比如:登陆认证拦截器,放在拦截器链中第一个位置。权限校验拦截器放在登陆拦截器之后。

例子:
实现登陆的拦截器
首先,需求:
拦截器检查url,是公共url放行,隐秘url需要验证是否登陆,没有登陆跳转到登陆页面,登陆则放行。

核心代码:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String url = request.getRequestURI();
if(url.indexOf("login.action") >= 0){
return true;
}
HttpSession session = request.getSession();
String username = (String)session.getAttribute("username");
if(username != null){
return true;
}
request.getServletDispatcher("/jsp/login.jsp").forwarld(request,response);

return false;
}



这里注意一点:return true和false仅仅表示的是中断后面的拦截器的执行和将拦截链继续下去,需要重定向等还是需要Redirect和Dispatcher。