文章目录
注:此篇文章适合对为什么自定义拦截器或者视图解析器生效的原因困惑的同学来看,带你从源码分析为什么。
一:WebMvcAutoConfiguration做了什么
1.WebMvcAutoConfiguration 源码
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
*****省略*******
}
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
从这里可以看到,这个自动配置类将会去主动加载以上的三个类,我们重点看WebMvcConfigurer.class
2.WebMvcConfigurer接口源码
可以看出,这是一个接口,里边声明了很多的方法,什么拦截器,视图解析器,格式转化器。既然是一个接口,我们看看是谁实现了它,那么实现的类就会被WebMvcAutoConfiguration 加载到。
3. WebMvcAutoConfigurationAdapter
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
*****省略*******
//实现类
public static class **WebMvcAutoConfigurationAdapter** implements WebMvcConfigurer {
*****
}
******省略******
}
震惊,实现类WebMvcAutoConfigurationAdapter居然是WebMvcAutoConfiguration 的静态内部类。所以说我们的WebMvcAutoConfiguration 会自动加载WebMvcAutoConfigurationAdapter的所有东西,因为WebMvcAutoConfigurationAdapter实现了WebMvcConfigurer接口。
4.自定义类实现WebMvcConfigurer这个接口,这样我们是不是就可以加上一些我们自己的配置了?试一试
4.1如果我们想增加拦截器,怎么做,先看源码
public interface WebMvcConfigurer {
//拦截器的声明
default void addInterceptors(InterceptorRegistry registry) {
}
}
可以看出拦截器需要一个InterceptorRegistry 拦截器注册器,我们点开看看
public class InterceptorRegistry {
private final List<InterceptorRegistration> registrations = new ArrayList<>();
public InterceptorRegistration addInterceptor(HandlerInterceptor interceptor) {
InterceptorRegistration registration = new InterceptorRegistration(interceptor);
this.registrations.add(registration);
return registration;
}
}
从上面的源码可以看到,InterceptorRegistry 有一个包含InterceptorRegistration的List,同时有一个addInterceptor的方法,主要内容是往这个list中增加InterceptorRegistration,我们点开InterceptorRegistration看看。
public class InterceptorRegistration {
private final HandlerInterceptor interceptor;
public InterceptorRegistration(HandlerInterceptor interceptor) {
Assert.notNull(interceptor, "Interceptor is required");
this.interceptor = interceptor;
}
}
可以看到InterceptorRegistration 他有一个HandlerInterceptor 的类属性,同时有一个构造方法来赋值。我们点开HandlerInterceptor 这个看看。
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 {
}
可以看到这是一个接口。我们可以写一个类实现这个接口。
4.2写代码实践下
先写一个我们的拦截器实现这个接口HandlerInterceptor
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
return true;
}
我们再写一个自己的配置类
@Configuration
public class MyConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//将我们自定义的拦截器加入配置
InterceptorRegistration interceptor = registry.addInterceptor(new MyInterceptor());
//设置拦截的url
interceptor.addPathPatterns("/user/**");
}
}
这样我们的自定义拦截器就写好啦。
如果想在webmvc中添加自己的功能,只需要去WebMvcConfigurer看看自己想增加什么功能就好啦,然后按照源码来写。