springmvc详解(3)请求分发流程之拦截器 HandlerInterceptor

174 阅读2分钟

前言

当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。
    这样我们就可以使用这些拦截器了。

总结

最后以一个流程图直观总结一下其过程: image.png