繼上篇實現路由功能 出現的小瑕疵

一,在上一篇博客中,我們已經可以實現自定義註解實現路由功能了,但是這裏實際上有點兒小瑕疵,那就是我們所些的Interceptor並沒有被加入到自定義的HandlerMappingHandlerTest中來,這是爲啥呢?

1,因爲我們在註冊爲一個Bean的時候,並沒有對Interceptor屬性進行設置。

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public HandlerMapping handlerMappingTest() {
        return new HandlerMappingHandlerTest();
    }
}

2,這就導致了內部沒有Interceptor,這時候,如果我們自定義了一個Interceptor。那麼這個interceptor在我們自己的HandlerMappingHandlerTest路由功能中是不起作用的。

public class InterceptorTest implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }
}

3,也就是說這是兩個體系。對於路由功能的解析和interceptor的註冊是一體的。但是不同的解析規則,需要自己添加Interceptor,Spring是不會將我們註冊給WebMvcConfigurer的Interceptor拿給我們來用的。

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public HandlerMapping handlerMappingTest() {
        HandlerMappingHandlerTest handlerTest = new HandlerMappingHandlerTest();
        handlerTest.setInterceptors(new InterceptorTest());// 這裏註冊給我們自定義的HandlerMappingHandlerTest
        return handlerTest;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new InterceptorTest());//這裏是註冊給Spring默認的RequestMappingHandlerMapping
    }
}

二,那麼問題來了,爲什麼Spring默認的RequestMappingHandlerMapping這個類可以拿到interceptor呢?

答案是因爲RequestMappingHandlerMapping的初始化是在WebMvcConfigurationSupport類中完成的。

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
        @Bean
	public RequestMappingHandlerMapping requestMappingHandlerMapping() {
		RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
		mapping.setOrder(0);
		mapping.setInterceptors(getInterceptors());//!!!這裏調用了下面的代碼!!!
		mapping.setContentNegotiationManager(mvcContentNegotiationManager());
		mapping.setCorsConfigurations(getCorsConfigurations());
                。。。// 省略
                {
                    protected final Object[] getInterceptors() {//!!!調用了這裏!!!
		        if (this.interceptors == null) {
			    InterceptorRegistry registry = new InterceptorRegistry();//我們自定義的所有interceptor都在這裏。但是這個方法的get屬性是protected的,外部拿不到
			    addInterceptors(registry);
			    registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService()));
			    registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
			    this.interceptors = registry.getInterceptors();
		        }
		        return this.interceptors.toArray();
                    }
                }

        }
}

 

而WebMvcConfigurationSupport內部可以調用所有註冊到InterceptorRegistry的信息,也就是下面接口的內容,其實就是我們可以配置的內容

public interface WebMvcConfigurer {


	default void addFormatters(FormatterRegistry registry) {// 格式化
	}

	default void addInterceptors(InterceptorRegistry registry) {// 攔截器
	}

	default void addResourceHandlers(ResourceHandlerRegistry registry) {//資源處理器
	}

	default void addCorsMappings(CorsRegistry registry) {// 跨域
	}

	default void addViewControllers(ViewControllerRegistry registry) {
	}

	default void configureViewResolvers(ViewResolverRegistry registry) {
	}

	default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {// 參數解析器
	}

	default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {//返回值處理器,添加自定義的返回值處理器可是實現統一回包格式的功能
	}

}

但是在包外這些內容去都是拿不到的,

/**
 * Configuration equivalent to {@code @EnableWebMvc}.
 */
@Configuration
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
    @Bean
    @Primary
    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        // Must be @Primary for MvcUriComponentsBuilder to work
        return super.requestMappingHandlerMapping();// 這裏註冊爲Bean,我們一般是在自己寫的config中註冊爲Bean, 但是在這裏註冊可以拿到註冊器,參數解析器,返回值處理器等。但是在包外的我們就拿不到,這就是親兒子的待遇啊!!!
    }
}

所以其實這裏可以給Spring一個小建議,那就是給

org.springframework.web.servlet.config.annotation.InterceptorRegistry這個類增加各種get方法。!!!

demo鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章