前言

当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


小燃儿
110 声望2 粉丝

java developer.