目录
一、什么是拦截器
Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。
所有 HandlerMapping
的实现都支持 handler 拦截器,当你想对某些请求应用特定的功能时,这些拦截器是非常有用的—例如,检查一个 principal。拦截器必须实现 org.springframework.web.servlet
包中的 HandlerInterceptor
,它有三个方法,应该可以提供足够的灵活性来进行各种预处理和后处理:
preHandle(..)
: 在实际 handler 运行之前postHandle(..)
: handler 运行后afterCompletion(..)
: 在整个请求完成后
preHandle(..)
方法返回一个boolean值。你可以使用这个方法来中断或继续执行链的处理。当这个方法返回 true
时,handler 执行链继续进行。当它返回 false
时, DispatcherServlet
认为拦截器本身已经处理了请求(例如,渲染了一个适当的视图),并且不继续执行其他拦截器和执行链中的实际 handler。
postHandle
方法在 @ResponseBody
和 ResponseEntity
方法中用处不大,因为这些方法的响应是在 HandlerAdapter
中和 postHandle
之前写入和提交的。这意味着对响应进行任何修改都太晚了,比如添加一个额外的 header。
二、拦截器配置
在Java配置中,你可以注册拦截器来应用于传入的请求,如下例所示:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LocaleChangeInterceptor()); registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**"); } }
下面的例子显示了如何在XML中实现同样的配置:
<mvc:interceptors> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/admin/**"/> <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/> </mvc:interceptor> </mvc:interceptors>
映射的拦截器并不适合作为安全层,因为它有可能与注解的控制器路径匹配不匹配,它也可以透明地匹配尾部斜线和路径扩展,以及其他路径匹配选项。这些选项中的许多已经被废弃,但错配的可能性仍然存在。一般来说,我们推荐使用Spring Security,它包括一个专门的 MvcRequestMatcher,与Spring MVC的路径匹配保持一致,同时还有一个安全防火墙(security firewall),可以阻止URL路径中许多不需要的字符。
三、定义拦截器
package com.doker.interceptor; public class MyInterceptor implements HandlerInterceptor { /** * 预处理,controller 方法执行前 * 应用:用于身份认证、身份授权 * return true 放行,执行下一个拦截器,如果没有,执行 controller 中的方法 * return false 不放行,即不向下执行 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle"); return true; } /** * 后处理方法,controller 方法执行后,方法跳转 success.jsp 执行之前 * 应用:从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图 */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); } /** * success.jsp 页面执行后,该方法会执行 * 应用:统一异常处理,统一日志处理 */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion"); } }
四、 多个拦截器
- 多个拦截器时,按照 springmvc.xml 配置的顺序执行。
- (2个拦截器时) 拦截器1 preHandle 不放行,postHandle 和 afterCompletion 不会执行。
- (2个拦截器时) 拦截器1 preHandle 不放行,拦截器2不执行。
<mvc:interceptors> <mvc:interceptor> <!--拦截的资源URI--> <mvc:mapping path="/**"/> <!--不拦截哪些--> <!--<mvc:exclude-mapping path="" />--> <bean id="handlerInterceptorDemo1" class="com.doker.interceptor.MyInterceptor"> </bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean id="handlerInterceptorDemo2" class="com.doker.interceptor.MyInterceptor1"> </bean> </mvc:interceptor> </mvc:interceptors>
所以,多个拦截器是按照配置的顺序决定的:handlerInterceptorDemo1—>handlerInterceptorDemo2。
官网:Doker 多克; 官方旗舰店:首页-Doker 多克 多克创新科技企业店-淘宝网 技术人的数码品牌!!!全品8折优惠,期待您的支持!!!