HandlerInterceptor 结构
拦截方法一般写在 preHandle()。
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;
void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;
}
sprng-mvc.xml 拦截器配置
当然要使此配置生效,还需要web.xml配置springMVC请求路径,这里就不多说了。
<!--拦截器, 对路径进行拦截-->
<mvc:interceptors>
<mvc:interceptor>
<!--拦截后台页面的请求-->
<mvc:mapping path="/back/**"/>
<!--<mvc:mapping path="/test/testMethod"/>-->
<!--不拦截登录页和登录的请求-->
<mvc:exclude-mapping path="/back/loginPage.htm"/>
<mvc:exclude-mapping path="/back/login.htm"/>
<bean class="com.ppf.test.inteceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
- 拦截器配置说明
如果只设置了 <mvc:mapping path="/**"/>
表明对一切进入SpringMVC的请求拦截。
如果这样设置 <mvc:mapping path="/back/**"/>
SpringMVC 会去映射表中查找对应的controller ,如果查找不到就不拦截。
原理
- DispatcherServlet会调doDispathc()方法 ,mappedHandler = this.getHandler(processedRequest); 获取 一个handler。这个handler怎么来的呢?
- 他会调 DispatcherServlet 的 getHandler 方法。这里可以看到 handler 其实就是 HandlerExecutionChain ,这个 handlerExecutionChain 是哪里的呢?
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Iterator var2 = this.handlerMappings.iterator();
HandlerExecutionChain handler;
do {
if (!var2.hasNext()) {
return null;
}
HandlerMapping hm = (HandlerMapping)var2.next();
if (this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
}
handler = hm.getHandler(request);
} while(handler == null);
return handler;
}
- handlerExecutionChain 其实是HandlerMapping 调用getHandler得到的。
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = this.getHandlerInternal(request);
if (handler == null) {
handler = this.getDefaultHandler();
}
if (handler == null) {
return null;
} else {
if (handler instanceof String) {
String handlerName = (String)handler;
handler = this.getApplicationContext().getBean(handlerName);
}
HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
CorsConfiguration config = globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig;
executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
}
- 这个 getHandlerExecutionChain 具体做了什么呢?
当然是获取 HandlerExecutionChain,本文重点探讨的拦截器就是在这里加的。
从中可以看出,配置文件中加的拦截器最后是在这里实现的。会通过我们的配置,查找添加对应的拦截器。
当mapping为空时,不拦截, 当mapping 不为空时,找到对应controller就添加拦截器,找不到就不添加,当设置 <mvc:mapping path="/**"/>,对所有请求添加拦截器。
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = handler instanceof HandlerExecutionChain ? (HandlerExecutionChain)handler : new HandlerExecutionChain(handler);
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
Iterator var5 = this.adaptedInterceptors.iterator();
while(var5.hasNext()) {
HandlerInterceptor interceptor = (HandlerInterceptor)var5.next();
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor)interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
// 添加拦截器
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
} else {
// 添加拦截器
chain.addInterceptor(interceptor);
}
}
return chain;
}
拦截器使用时机
在controller 调用之前 处理,和在 controller 调用之后处理