一,在上一篇博客中,我們已經可以實現自定義註解實現路由功能了,但是這裏實際上有點兒小瑕疵,那就是我們所些的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, 但是在這裏註冊可以拿到註冊器,參數解析器,返回值處理器等。但是在包外的我們就拿不到,這就是親兒子的待遇啊!!!
}
}