一.背景介绍
Interceptor作为SpringMVC最重要的组件之一,它可以帮助我们在调用接口的前后做一个自定义的拓展。
二.源码分析
调用栈
getInterceptor:147, InterceptorRegistration (org.springframework.web.servlet.config.annotation) getInterceptors:74, InterceptorRegistry (org.springframework.web.servlet.config.annotation) getInterceptors:368, WebMvcConfigurationSupport (org.springframework.web.servlet.config.annotation) welcomePageHandlerMapping:443, WebMvcAutoConfiguration$EnableWebMvcConfiguration (org.springframework.boot.autoconfigure.web.servlet) createBeanInstance:1195, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) doCreateBean:582, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) createBean:542, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
HandlerInterceptor
SpringMVC拦截器
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 {
}
}
1.创建并注册拦截器
自定义拦截器MyHandlerInterceptor
@Component
public class MyHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyHandlerInterceptor preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyHandlerInterceptor postHandle");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyHandlerInterceptor afterCompletion");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
自定义SpringWebMVC配置类(目的配置已注册的拦截器,让它生效)
@Configuration
public class MyWebMvcAutoConfiguration implements WebMvcConfigurer {
@Autowired
private MyHandlerInterceptor myHandlerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myHandlerInterceptor).addPathPatterns("/**").order(1);
}
}
DelegatingWebMvcConfiguration
委任webmvc配置器,主要是检测WebMvcConfigurer,允许我们自定义WebMvcConfigurationSupport提供的配置。这是@EnableWebMvc实际导入的类。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
在popularBean(DelegatingWebMvcConfiguration)的时候先执行setConfigurers,将所有自定义的WebMVC配置类创建Bean对象,并装载进WebMvcConfigurerComposite
这一步就相当于注册自定义SpringWebMvc
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
...............
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
this.configurers.addInterceptors(registry);
}
...............
}
WebMvcAutoConfiguration
主要将一些MVC需要的Bean对象注册进来(之后会单独文章讲注册进来每个Bean的职责)
@AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class WebMvcAutoConfiguration {
..................
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(WebProperties.class)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
return welcomePageHandlerMapping;
}
}
.................
}
在注册WelcomePageHandlerMapping Bean对象的时候,执行getInterceptors
1.getInterceptors(mvcConversionService, mvcResourceUrlProvider)
获取全部的拦截器,如果是首次去拿,拿不到就会进行一个注册拦截器的操作。可以看到创建了一个InterceptorRegistry对象,
2.DelegatingWebMvcConfiguration.addInterceptors(registry);
主要就是将InterceptorRegistry set到每个WebMvcConfiguer。
3.registry.getInterceptors()
登记所有的拦截器,触发判断拦截器是否需要构建MappedInterceptor
protected final Object[] getInterceptors(
FormattingConversionService mvcConversionService,
ResourceUrlProvider mvcResourceUrlProvider) {
if (this.interceptors == null) {
InterceptorRegistry registry = new InterceptorRegistry();
addInterceptors(registry);
registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService));
registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider));
this.interceptors = registry.getInterceptors();
}
return this.interceptors.toArray();
}
4.welcomePageHandlerMapping.setInterceptors()
这里因为welcomePageHandlerMapping需要用到interceptors。
public void setInterceptors(Object... interceptors) {
this.interceptors.addAll(Arrays.asList(interceptors));
}
WebMvcConfigurerComposite
存放WebMvcConfigurer实现类的容器,对所有WebMvcConfigurer做一些操作。
1.addInterceptors(InterceptorRegistry registry)
去执行每个webMvc调用registry.addInterceptors将自定义的拦截器封装成InterceptorRegistration
class WebMvcConfigurerComposite implements WebMvcConfigurer {
private final List<WebMvcConfigurer> delegates = new ArrayList<>();
@Override
public void addInterceptors(InterceptorRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addInterceptors(registry);
}
}
}
InterceptorRegistry
Interceptor注册表,可以理解为InterceptorRegistration的容器。主要负责InterceptorRegistration的创建和协助创建MappedInterceptor
public class InterceptorRegistry {
private final List<InterceptorRegistration> registrations = new ArrayList<>();
public InterceptorRegistration addInterceptor(HandlerInterceptor interceptor) {
InterceptorRegistration registration = new InterceptorRegistration(interceptor);
this.registrations.add(registration);
return registration;
}
protected List<Object> getInterceptors() {
return this.registrations.stream()
.sorted(INTERCEPTOR_ORDER_COMPARATOR)
.map(InterceptorRegistration::getInterceptor)
.collect(Collectors.toList());
}
}
InterceptorRegistration
Interceptor登记器,也就是把自定义的拦截器对象先封装成统一的InterceptorRegistration对象,然后主要的功能就是创建MappedInterceptor拦截器对象
1.getInterceptor()
这里的getInterceptor()跟上面的不同,这里主要构建Patterns的拦截器。有set Patterns就创建MappedInterceptor拦截器,没有就直接返回当前的Interceptor。
public class InterceptorRegistration {
private final HandlerInterceptor interceptor;
@Nullable
private List<String> includePatterns;
@Nullable
private List<String> excludePatterns;
@Nullable
private PathMatcher pathMatcher;
private int order = 0;
public InterceptorRegistration(HandlerInterceptor interceptor) {
Assert.notNull(interceptor, "Interceptor is required");
this.interceptor = interceptor;
}
public InterceptorRegistration addPathPatterns(String... patterns) {
return addPathPatterns(Arrays.asList(patterns));
}
public InterceptorRegistration addPathPatterns(List<String> patterns) {
this.includePatterns = (this.includePatterns != null ?
this.includePatterns : new ArrayList<>(patterns.size()));
this.includePatterns.addAll(patterns);
return this;
}
public InterceptorRegistration excludePathPatterns(String... patterns) {
return excludePathPatterns(Arrays.asList(patterns));
}
public InterceptorRegistration excludePathPatterns(List<String> patterns) {
this.excludePatterns = (this.excludePatterns != null ?
this.excludePatterns : new ArrayList<>(patterns.size()));
this.excludePatterns.addAll(patterns);
return this;
}
public InterceptorRegistration pathMatcher(PathMatcher pathMatcher) {
this.pathMatcher = pathMatcher;
return this;
}
public InterceptorRegistration order(int order){
this.order = order;
return this;
}
protected int getOrder() {
return this.order;
}
protected Object getInterceptor() {
if (this.includePatterns == null && this.excludePatterns == null) {
return this.interceptor;
}
MappedInterceptor mappedInterceptor = new MappedInterceptor(
StringUtils.toStringArray(this.includePatterns),
StringUtils.toStringArray(this.excludePatterns),
this.interceptor);
if (this.pathMatcher != null) {
mappedInterceptor.setPathMatcher(this.pathMatcher);
}
return mappedInterceptor;
}
}
2.调用拦截器
DispatcherServlet
处理器/控制器的中央调度程序(后面会开一篇文章专门讲DispatcherServlet)
1.mappedHandler = getHandler(processedRequest)
public class DispatcherServlet extends FrameworkServlet {
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
}
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
}
2.执行前的拦截操作
mappedHandler.applyPreHandle(processedRequest, response)
3.执行具体的服务
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
4.执行后的拦截操作
mappedHandler.applyPostHandle(processedRequest, response, mv);
5.执行服务完成之后的拦截操作
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
mappedHandler.triggerAfterCompletion(request, response, null);
HandlerExecutionChain
处理程序执行链,由处理程序对象和任何处理程序拦截器组成
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
private final Object handler;
private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
private int interceptorIndex = -1;
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
return true;
}
/**
* Apply postHandle methods of registered interceptors.
*/
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
interceptor.postHandle(request, response, this.handler, mv);
}
}
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
/**
* Apply afterConcurrentHandlerStarted callback on mapped AsyncHandlerInterceptors.
*/
void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (interceptor instanceof AsyncHandlerInterceptor) {
try {
AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptor;
asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
}
catch (Throwable ex) {
if (logger.isErrorEnabled()) {
logger.error("Interceptor [" + interceptor + "] failed in afterConcurrentHandlingStarted", ex);
}
}
}
}
}
}