springmvc拦截器的定义和配置
- Springmvc的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理
- springmvc拦截器的定义: 在springmvc中,定义拦截器要实现HandlerInterceptor接口,并实现该接口中提供的三个方法
- preHandle方法:进入Handler方法之前执行。可以用于身份认证、身份授权。比如如果认证没有通过表示用户没有登陆,需要此方法拦截不再往下执行(return false),否则就放行(return true)
- postHandle方法:进入Handler方法之后,返回ModelAndView之前执行。可以看到该方法中有个modelAndView的形参。应用场景:从modelAndView出发:将公用的模型数据(比如菜单导航之类的)在这里传到视图,也可以在这里同一指定视图
- afterCompletion方法:执行Handler完成之后执行。应用场景:统一异常处理,统一日志处理等。
- springmvc拦截器的配置
- 在springmvc中,拦截器是针对具体的HandlerMapping进行配置的,也就是说如果在某个HandlerMapping中配置拦截,经过该 HandlerMapping映射成功的handler最终使用该拦截器
- 假设我们在配置文件中配置了的映射器是org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
<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="ssm.intercapter.HandlerInterceptor1"/>
<bean id="handlerInterceptor2" class="ssm.intercapter.HandlerInterceptor2"/>
==配置类似于全局的拦截器==,建议使用
- springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中,这样就可以成为全局的拦截器了
<!-- springmvc配置类似于全局的拦截器 --> <mvc:interceptors> <!-- 多个拦截器,按顺序执行 --> <mvc:interceptor> <!-- 指定要拦截的url --> <mvc:mapping path="/**"/> <!-- 表示拦截所有的url包括子url路径 --> <bean class="com.td.interceptor.HandlerInterceptor1"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.td.interceptor.HandlerInterceptor2"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.td.interceptor.HandlerInterceptor3"/> </mvc:interceptor> </mvc:interceptors>
- springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中,这样就可以成为全局的拦截器了
拦截器的执行顺序
- 定义三个拦截器进行测试
- 三个拦截器都放行,将三个拦截器的方法的返回值都改为true,拦截器的执行顺序如下
- 测试结果:
- 当多有的拦截器都放行的时候,preHanler方法是按照配置的顺序执行的,其他方法是按照配置的顺序逆向执行的
- 第三个拦截器不放行,其他拦截器放行
- 测试结果:
- ==总结==:
- 因为拦截器1和拦截器2放行,拦截器3的preHandler方法才可以执行,前面的拦截器放行后面的拦截器才会执行preHandler
- 拦截器3不放行,拦截器3的另外两个方法不会被执行,也就是如果某个拦截器不放行,那么它的另外两个方法就不会执行
- 只要有一个拦截器不放行,所有拦截器的postHandler方法都不会执行,但是只好执行过 preHandler并且放行的拦截器,就会执行afterCompletion方法
- 三个拦截器都不放行
- 测试结果:
- 原因同上
- 三个拦截器都放行,将三个拦截器的方法的返回值都改为true,拦截器的执行顺序如下
拦截器的使用
- 根据拦截器执行顺序的第二中情况:比如现在要写一个统一异常处理的逻辑,那么要将该拦截器放在拦截器链的第一个位置,且一定要放行,因为只有放行了,才会去执行afterCompletion,而且放在拦截器链的第一个的话,afterCompletion方法会最后执行,才能在里面执行统一异常处理的逻辑。
- 登陆认证拦截器,放在拦截器链接中第一个位置(如果有统一异常处理,那么应该放在统一异常处理的后面)。权限校验拦截器,放在登陆认证拦截器之后(因为登陆通过后才校验权限)。
实例:登录认证拦截器
- 思路:
- 首先拦截到用户访问的url,判断如果这个url是公开的地址(不需要登录就可以访问的,那么就return true 放行)
- 其次判断,Session中的用户信息,如果存在,直接放行
- 最后,也就是没有用户的登录信息,转发到登录页面
- 实现登录的Controller方法
- 拦截器
- 配置拦截器
- 登录代码: