前言
当 Servlet 接管到申请后会最终调用 doDispatch 办法后会去找到对应的 HandlerMapping,同时也会找到配置的拦截器,最终组成须要的 HandlerExecutionChain 执行链(这里省略局部代码保留次要性能):
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 1. 确定应用的 handler
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {noHandlerFound(processedRequest, response);
return;
}
// 确定 handler 的适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 拦截器前置调用
if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}
// 理论调用
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 设置默认视图名
applyDefaultViewName(processedRequest, mv);
// 拦截器后置调用
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 散发后果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
拦截器
在开发中拦截器的应用是比拟频繁的,例如用户拦截器,权限拦截器等。sringmvc 的拦截器提供了 pre,post,after 三种期间的办法(调用处理器办法前,调用后,返回数据后),十分不便的进行资源设置,开释等性能。
public interface HandlerInterceptor {
// 前
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {return true;}
// 中
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception { }
// 后
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {}}
拦截器注册
当初看看拦截器是怎么注册的?spring 提供两种形式。
1. 配置类注册 EnableWebMvcConfiguration#setConfigurers
通常在开发中咱们会应用本人编写实现 WebMvcConfigurer 接口的形式增加拦截器,并把注册类注册到 IOC 容器中,EnableWebMvcConfiguration#setConfigurers 就会应用 @Autowired 进行制动注入。```java
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {if (!CollectionUtils.isEmpty(configurers)) {this.configurers.addWebMvcConfigurers(configurers);
}
}
```
最初把注册的拦截器注册到 HandlerMapping 当中去,(以 RequestMappingHandlerMapping 为例)代码如下,getInterceptors 办法最终会调用所有 WebMvcConfigurer 实例增加拦截器的办法,从而将咱们自定义的拦截器注册到 HanderMapping 当中去
```java
public RequestMappingHandlerMapping requestMappingHandlerMapping(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
mapping.setOrder(0);
mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
……
```
2. 以 MappedInterceptor 类实例或者子类间接注册到 IOC 容器中
因为 HandlerMapping 继承 WebApplicationObjectSupport,再创立 bean 的时候会调用其 initApplicationContext 办法。而该办法会注册容器中的 MappedInterceptor 类的 bean。这样咱们就能够应用这些拦截器了。
总结
最初以一个流程图直观总结一下其过程: