一,在上一篇博客中,我们已经可以实现自定义注解实现路由功能了,但是这里实际上有点儿小瑕疵,那就是我们所些的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, 但是在这里注册可以拿到注册器,参数解析器,返回值处理器等。但是在包外的我们就拿不到,这就是亲儿子的待遇啊!!!
}
}