SpringMVC源码系列文章
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xc.mvc</groupId>
<artifactId>springmvc</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.27</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!--配置Maven中Java的编译版本 -->
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
/**
* web工程的初始化类,用来代替web.xml
* 以下配置的都是以前在web.xml中配置的
*/
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* Spring的配置,目前不涉及Spring,这里设置为空
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[0];
}
/**
* SpringMVC的配置
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{SpringMVCConfig.class};
}
/**
* 用于配置DispatcherServlet的映射路径
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
/**
* 注册过滤器
*/
@Override
protected Filter[] getServletFilters() {
// 字符编码过滤器
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
// HiddenHttpMethodFilter 用于支持 PUT、DELETE 等 HTTP 请求
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter};
}
}
// 将当前类标识为一个配置类
@Configuration
// 仅仅扫描@Controller、@RestController
@ComponentScan(
value = "com.xc",
includeFilters = {@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = {Controller.class, RestController.class}
)},
// 默认扫描 @Component @Repository, @Service, or @Controller
useDefaultFilters = false
)
// mvc注解驱动
@EnableWebMvc
public class SpringMVCConfig implements WebMvcConfigurer {
// 拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
MyInterceptor myInterceptor = new MyInterceptor();
registry.addInterceptor(myInterceptor).addPathPatterns("/**");
}
}
拦截器
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("处理器方法前调用");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("处理器方法后调用");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("渲染完成后调用");
}
}
// 接受User对象修改并返回
@PostMapping("/test")
@ResponseBody
public User test(@RequestBody User user) {
// 修改名字为李四然后返回给前台
user.setName("李四");
System.out.println(user);
return user;
}
启动tomcat发送请求结果
初始化
**的工作,例如注册servlet或者filtes等 ServletContainerInitializer接口
**实现此功能META-INF/services
**目录创建一个名为**javax.servlet.ServletContainerInitializer
**的文件 ServletContainerInitializer实现类
**ps:JDK会自动加载META-INF/services目录下的类(深入理解SPI机制) 容器在启动应用的时候,会扫描当前应用每一个jar包里面META-INF/services指定的实现类(tomcat默认读取)
WebApplicationInitializer接口
**的类,然后赋值给onStartup方法的webAppInitializerClasses参数感兴趣的类
**(WebApplicationInitializer)信息onStartup
**方法// SpringServletContainerInitializer类
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = Collections.emptyList();
// 如果找不到WebApplicationInitializer的实现类,webAppInitializerClasses就为null
if (webAppInitializerClasses != null) {
initializers = new ArrayList<>(webAppInitializerClasses.size());
for (Class<?> waiClass : webAppInitializerClasses) {
// 判断实现类不是接口抽象类,即正常的接口实现类
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
// 反射创建对象,并添加到集合中,后面统一遍历调用onStartup方法
initializers.add((WebApplicationInitializer)
ReflectionUtils.accessibleConstructor(waiClass).newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
}
// 集合为空,证明没找到实现类,直接返回
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
}
// 排序,证明WebApplicationInitializer的实现类有先后顺序
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
// 调用WebApplicationInitializer接口实现类的onStartup方法
initializer.onStartup(servletContext);
}
}
}
// WebApplicationInitializer接口
public interface WebApplicationInitializer {
/**
* 初始化此Web应用程序所需的任何Servlet、过滤器、侦听器上下文参数和属性配置给定的ServletContext
*/
void onStartup(ServletContext servletContext) throws ServletException;
}
WebApplicationInitializer接口与自定义配置类WebAppInitalizer(代替web.xml)关系
总结**SpringServletContainerInitializer
**作用:加载自定义的**WebApplicationInitializer初始化核心接口
**的实现类WebAppInitializer,调用**onStartup
**方法来实现web容器初始化。
自定义配置类WebAppInitializer(代替web.xml)的类图如下:
由上一节可知,web容器初始化工作会调用自定义配置类的onStartup方法,那就是**根据类图从下往上找onStartup方法调用
**,WebAppInitializer和AbstractAnnotationConfigDispatcherServletInitializer中都没有onStartup方法,那么首先进入**AbstractDispatcherServletInitializer
**重写的onStartup方法,核心内容**注册前端控制器
**。
DispatcherServlet的映射路径
**的方法注册过滤器
**的方法// AbstractDispatcherServletInitializer类的方法
protected void registerDispatcherServlet(ServletContext servletContext) {
// 获取servlet名称,常量“dispatcher”
String servletName = getServletName();
// 创建一个web应用程序子容器
WebApplicationContext servletAppContext = createServletApplicationContext();
// 创建DispatcherServlet对象,将上下文设置到dispatcherServlet中
FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
// 设置servlet容器初始化参数(这里不设置一般默认为null)
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
// 把servlet添加到Tomcat容器中
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
if (registration == null) {
throw new IllegalStateException("Failed to register servlet with name '" + servletName + "'. " +
"Check if there is another servlet registered under the same name.");
}
// 将前端控制器初始化提前到服务器启动时,否则调用时才会初始化
registration.setLoadOnStartup(1);
// 添加servlet映射,拦截请求
// 调用自定义配置类重写的getServletMappings方法
registration.addMapping(getServletMappings());
// 设置是否支持异步,默认true
registration.setAsyncSupported(isAsyncSupported());
// 获取所有的过滤器getServletFilters方法
// 调用自定义配置类重写的getServletMappings方法
Filter[] filters = getServletFilters();
if (!ObjectUtils.isEmpty(filters)) {
for (Filter filter : filters) {
registerServletFilter(servletContext, filter);
}
}
// 空方法,可以再对dispatcherServlet进行处理
customizeRegistration(registration);
}
SpringMVC配置
**的方法// AbstractAnnotationConfigDispatcherServletInitializer类方法
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
// 调用自定义配置类的设置子容器配置文件的方法
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
context.register(configClasses);
}
return context;
}
DispatcherServlet
**对象,传入web容器// AbstractDispatcherServletInitializer类方法
protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
return new DispatcherServlet(servletAppContext);
}
Tomcat
**容器的过滤器集合中protected FilterRegistration.Dynamic registerServletFilter(ServletContext servletContext, Filter filter) {
String filterName = Conventions.getVariableName(filter);
Dynamic registration = servletContext.addFilter(filterName, filter);
...
registration.setAsyncSupported(isAsyncSupported());
registration.addMappingForServletNames(getDispatcherTypes(), false, getServletName());
return registration;
}
小结一下
没有初始化
**DispatcherServlet类图如下:
Tomcat启动容器加载Servelt(这里是DispatcherServlet)并初始化,就会调用到这里。之前文章Tomcat源码解析(五):StandardEngine、StandardHost、StandardContext、StandardWrapper中有介绍。
web容器的刷新
**抽象类AbstractApplicationContext
**的**refresh
**方法,看过spring源码的应该很熟悉web容器
**和**spring容器
**都间接继承了AbstractApplicationContext,**容器刷新
**都调用如下方法** 容器初始化时候有个很重要的**bean工厂后置处理器ConfigurationClassPostProcessor
**,作用就是解析**@Configuration,@Import,@ComponentScan,@Bean
**等注解给bean容器**添加bean定义
**,之前文章Spring源码解析(六):bean工厂后置处理器ConfigurationClassPostProcessor有介绍。
接下来的入口就在**自定义g配置类SpringMVCConfi
**这里,因为它的配置类注解**@Configuration
**(也是@Component),**@ComponentScan(扫描@Controller注解)
**和**@EnableWebMvc(导入DelegatingWebMvcConfiguration.class)
**注解都会被扫描解析到。
@EnableWebMvc
在讲DelegatingWebMvcConfiguration之前先说下WebMvcConfigurer接口,因为下面内容都是围绕着WebMvcConfigurer接口展开的。
WebMvcConfigurer是一个接口,它提供了一种扩展SpringMVC配置的方式。通过实现WebMvcConfigurer接口,可以**定制化SpringMVC的配置
**,例如添加拦截器、跨域设置、方法参数解析器、返回值处理、消息转换器、异常处理器
public interface WebMvcConfigurer {
...
// 配置拦截器
default void addInterceptors(InterceptorRegistry registry) {
}
// 配置跨域
default void addCorsMappings(CorsRegistry registry) {
}
// 配置视图解析器
default void configureViewResolvers(ViewResolverRegistry registry) {
}
// 配置方法参数解析器(解析@RequestBody就是通过HandlerMethodArgumentResolver接口实现的)
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
}
// 配置方法返回值(解析@ResponseBody就是通过HandlerMethodReturnValueHandler接口实现的)
default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
}
// 配置消息转换器(此时可能还没有转换器)
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
// 扩展消息转换器(至少已存在默认转换器)
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
// 配置异常处理器
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
...
}
DelegatingWebMvcConfiguration的类图如下:
WebMvcConfigurer
**接口重写对应方法即可所有WebMvcConfigurer接口实现类
**注入进来,放入configurers的List<WebMvcConfigurer> delegates属性中@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
// WebMvcConfigurerComposite实现WebMvcConfigurer,内部有个WebMvcConfigurer集合
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
// 注入一组WebMvcConfigurer,这些WebMvcConfigurer由开发人员提供,或者框架其他部分提供
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
...
// 如下方法都是重写父类WebMvcConfigurationSupport
// 与WebMvcConfigurer接口中的方法一样,配置拦截器、跨域配置等
@Override
protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
this.configurers.configureDefaultServletHandling(configurer);
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
this.configurers.addInterceptors(registry);
}
@Override
protected void addCorsMappings(CorsRegistry registry) {
this.configurers.addCorsMappings(registry);
}
@Override
protected void configureViewResolvers(ViewResolverRegistry registry) {
this.configurers.configureViewResolvers(registry);
}
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
this.configurers.configureMessageConverters(converters);
}
@Override
protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
this.configurers.configureHandlerExceptionResolvers(exceptionResolvers);
}
...
}
调用DelegatingWebMvcConfiguration重写的MVC配置方法实际就是**对应的配置添加到对应的注册器
**中。如所有的拦截器都会被添加到**InterceptorRegistry(拦截器注册器)
**、所有跨域配置则会被添加到**CorsRegistry(跨域注册器)
**,不用说对应的注册器中肯定维护着对应的配置集合。
// WebMvcConfigurerComposite类
class WebMvcConfigurerComposite implements WebMvcConfigurer {
private final List<WebMvcConfigurer> delegates = new ArrayList<>();
@Override
public void addInterceptors(InterceptorRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addInterceptors(registry);
}
}
@Override
public void addCorsMappings(CorsRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addCorsMappings(registry);
}
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureViewResolvers(registry);
}
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureMessageConverters(converters);
}
}
}
在上面说到WebMvcConfigurationSupport类中定义了与WebMvcConfigurer接口一样的配置方法,都是空实现,由子类DelegatingWebMvcConfiguration重写,遍历所有WebMvcConfigurer的实现类,将对应配置添加到对应注册器中。
另外一方面在WebMvcConfigurationSupport类中有很多**@Bean
**方法,即bean定义,返回值即为创建的**bean对象
**。其中有两个很重要,**映射器RequestMappingHandlerMapping
**和**适配器RequestMappingHandlerAdapter
**。
映射器HandlerMapping
public interface HandlerMapping {
/**
* 获取执行器链(包括Handler和拦截器)
*/
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
匹配/映射
**上能够处理当前request的Handler@Controller
**,结合**@RequestMapping("/test")
**HandlerMapping
**,有很多实现类RequestMappingHandlerMapping
**处理适配器HandlerAdapter
public interface HandlerAdapter {
/**
* 因为有多个HandlerMapping和HandlerAdapter
* 对于HandlerAdapter是否支持对应的HandlerMapping,通过此方法判断
*/
boolean supports(Object handler);
/**
* 具体调用Hangder的方法
*/
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
Handler
**是**不确定类型
**的 不统一
**的RequestMappingHandlerAdapter
**就是处理@RequestMapping注解的Handler**// WebMvcConfigurationSupport类方法
@Bean
@SuppressWarnings("deprecation")
public RequestMappingHandlerMapping requestMappingHandlerMapping(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
// 创建RequestMappingHandlerMapping对象
RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
// 设置排序为0,以后会遍历所有HandlerMapping,排序0的话,则会先遍历
// 简单说@RequestMaping注解使用概率大,先用RequestMappingHandlerMapping处理
mapping.setOrder(0);
// 设置所有的拦截器,并排序
mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
mapping.setContentNegotiationManager(contentNegotiationManager);
// 设置所有的跨域配置
mapping.setCorsConfigurations(getCorsConfigurations());
// 省略各种匹配url的属性,如url正则匹配等等,我们这次只考虑url正常匹配
...
return mapping;
}
这里先创建**拦截器注册器InterceptorRegistry
**,然后调用DelegatingWebMvcConfiguration重写WebMvcConfigurationSupport的添加拦截器方法addInterceptors,这样所有拦截器就都会被添加到**InterceptorRegistry registry
**中。最后将我们自定义的拦截器组成**MappedInterceptor
**。
// WebMvcConfigurationSupport
protected final Object[] getInterceptors(
FormattingConversionService mvcConversionService,
ResourceUrlProvider mvcResourceUrlProvider) {
if (this.interceptors == null) {
InterceptorRegistry registry = new InterceptorRegistry();
// 这里就是调用DelegatingWebMvcConfiguration重写的方法
addInterceptors(registry);
// 这是两个设置setAttribute值的拦截器,不用深入研究
registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService));
registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider));
// 这里会将上面我们自己设置的拦截器包装一层返回
this.interceptors = registry.getInterceptors();
}
return this.interceptors.toArray();
}
这里将我们所有自定义拦截器都这样包装一层,因为是以后为了统一管理,这个**MappedInterceptor
**拦截器里面有个很重要**方法matches(此次请求是否匹配当前拦截器
**),就是筛选拦截器链使用的。
也是先**创建跨域注册器CorsRegistry
**,然后调用然后调用DelegatingWebMvcConfiguration重写WebMvcConfigurationSupport的添加跨域方法addCorsMappings,也是添加到**CorsRegistry registry
**中。
// WebMvcConfigurationSupport
protected final Map<String, CorsConfiguration> getCorsConfigurations() {
if (this.corsConfigurations == null) {
CorsRegistry registry = new CorsRegistry();
addCorsMappings(registry);
this.corsConfigurations = registry.getCorsConfigurations();
}
return this.corsConfigurations;
}
RequestMappingHandlerMapping的复杂类图看一下(有删减)
@RequestMapping注解肯定是在容器启动时候解析的,那么这个工作就放在RequestMappingHandlerMapping这个bean对象的初始化阶段来完成。之前文章Spring源码解析(四):单例bean的创建流程有介绍过,bean对象创建后会调用各种初始化方法,其实就包括调用**InitializingBean接口
**的**afterPropertiesSet
**方法来**实现初始化
**。
// RequestMappingHandlerMapping类方法
@Override
@SuppressWarnings("deprecation")
public void afterPropertiesSet() {
// 创建RequestMappingInfo对象
this.config = new RequestMappingInfo.BuilderConfiguration();
this.config.setTrailingSlashMatch(useTrailingSlashMatch());
this.config.setContentNegotiationManager(getContentNegotiationManager());
if (getPatternParser() != null) {
this.config.setPatternParser(getPatternParser());
Assert.isTrue(!this.useSuffixPatternMatch && !this.useRegisteredSuffixPatternMatch,
"Suffix pattern matching not supported with PathPatternParser.");
}
else {
this.config.setSuffixPatternMatch(useSuffixPatternMatch());
this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
this.config.setPathMatcher(getPathMatcher());
}
// 调用父类实现的afterPropertiesSet方法
super.afterPropertiesSet();
}
// AbstractHandlerMethodMapping类方法
/**
* 在初始化时检测处理程序方法
*/
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
/**
* 扫描 ApplicationContext 中的 Bean,检测并注册处理程序方法
*/
protected void initHandlerMethods() {
// 获取所有的bean对象并遍历
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
// 筛选候选的bean
processCandidateBean(beanName);
}
}
// getHandlerMethods()获取请求路径与具体Controller方法的映射关系
handlerMethodsInitialized(getHandlerMethods());
}
// AbstractHandlerMethodMapping类方法
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
try {
// 获取bean对象的Class类型
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
...
}
// 判断是否处理程序
if (beanType != null && isHandler(beanType)) {
// 查找处理程序的方法
detectHandlerMethods(beanName);
}
}
@Controller
**或**@RequestMapping
**注解判断是否为处理程序// RequestMappingHandlerMapping
@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
Method
**方法上是否有**@RequestMapping
**注解RequestMappingInfo
**Method
**对象RequestMappingInfo
**对象// AbstractHandlerMethodMapping类方法
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
// 类如果被代理,获取真正的类型
Class<?> userType = ClassUtils.getUserClass(handlerType);
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
...
}
});
...
// 注册Handler方法(将请求路径、RequestMappingInfo、Controller#Method统一放一起)
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
// RequestMappingHandlerMapping类方法
@Override
@Nullable
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = createRequestMappingInfo(method);
...
return info;
}
Controller类
**下**@RequestMapping
**注解方法registerHandlerMethod:注册Handler方法(将请求路径、RequestMappingInfo、Controller#Method统一放到MappingRegistry对象中)
内部类MappingRegistry
**类的**register
**方法// AbstractHandlerMethodMapping的内部类MappingRegistry类方法
class MappingRegistry {
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
private final MultiValueMap<String, T> pathLookup = new LinkedMultiValueMap<>();
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
// handler(Controller对象)与有@RequestMapping的Method组成对象HandlerMethod
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
// 校验@RequestMapping注解内容是否注册过
validateMethodMapping(handlerMethod, mapping);
// 获取@RequestMapping注解映射的路径,因为可以设置多个,所以这里是集合
Set<String> directPaths = AbstractHandlerMethodMapping.this.getDirectPaths(mapping);
for (String path : directPaths) {
this.pathLookup.add(path, mapping);
}
...
// 获取@CrossOrigin获取CorsConfiguration,并初始化跨域的默认值,最后跨域配置添加到corsLookup
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
corsConfig.validateAllowCredentials();
this.corsLookup.put(handlerMethod, corsConfig);
}
// 各类属性配置组成对象MappingRegistration,然后添加到registry中
this.registry.put(mapping,
new MappingRegistration<>(mapping, handlerMethod, directPaths, name, corsConfig != null));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
}
MappingRegistry
**(映射注册器),以后的mapping映射什么都放这里** @RequestMapping
**注解的**映射路径
**RequestMappingInfo
**对象(@RequestMapping注解属性组成的对象)@CrossOrigin
**注解的跨域配置RequestMappingInfo
**对象MappingRegistration
**对象(RequestMappingInfo、HandlerMethod、CorsConfiguration组成的对象)There is already 'xxx' bean method
**(这个大家应该很熟悉)// AbstractHandlerMethodMapping类方法
public Map<T, HandlerMethod> getHandlerMethods() {
this.mappingRegistry.acquireReadLock();
try {
return Collections.unmodifiableMap(
this.mappingRegistry.getRegistrations().entrySet()
.stream().collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().handlerMethod)
));
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
protected void handlerMethodsInitialized(Map<T, HandlerMethod> handlerMethods) {
// 获取到上面拿到的值,打印数量
int total = handlerMethods.size();
if ((logger.isTraceEnabled() && total == 0) || (logger.isDebugEnabled() && total > 0) ) {
logger.debug(total + " mappings in " + formatMappingName());
}
}
// WebMvcConfigurationSupport类方法
private static final boolean jackson2Present;
// 加载对应的类,能加载成功方true,不能加载成功,表示没有这个类,没有导入包,返回false
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcValidator") Validator validator) {
// 创建RequestMappingHandlerAdapter对象
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
adapter.setContentNegotiationManager(contentNegotiationManager);
// 设置消息转换器
adapter.setMessageConverters(getMessageConverters());
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
adapter.setCustomArgumentResolvers(getArgumentResolvers());
adapter.setCustomReturnValueHandlers(getReturnValueHandlers());
// 如果导入Jackson包,则添加
if (jackson2Present) {
// 处理jackson中的@JsonView的字段,过滤输出的字段,具体实现以后单独讲
adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
}
// 省略异步配置,以后再研究
...
return adapter;
}
MediaType类
**:表示互联网中多媒体数据类型的格式;例如:text/html,text/plain,application/json…**canRead方法
**:检查能否将请求信息转换为mediaType表示的数据类型,这个mediaType是前端页面请求时设定的contentType格式**read方法
**:如果canRead方法返回值为true,则调用read方法将请求信息转换为T类型对象**canWrite方法
**:检查clazz对象是否能转换为mediaType类型,此时的mediaType表示后端想要响应给前端的数据格式**write方法
**:如果canWrite返回值为true,则将T类型的对象写到响应流中,同时指定mediaType类型** 先调用DelegatingWebMvcConfiguration重写的方法,也就是遍历所有**WebMvcConfigurer实现类
**,调用他们的**configureMessageConverters
**方法,**新增
**的消息转换器都会添加到**messageConverters集合中
**。如果开发者和第三方都没有添加,那么设置默认的消息转换器,设置完以后,再调用**扩展方法
**,也就是遍历所有WebMvcConfigurer实现类,调用他们的**extendMessageConverters
**方法,对消息转换器做最后**修改
**。
// WebMvcConfigurationSupport
protected final List<HttpMessageConverter<?>> getMessageConverters() {
if (this.messageConverters == null) {
this.messageConverters = new ArrayList<>();
// 这里就是调用DelegatingWebMvcConfiguration重写的方法,配置消息转换器
configureMessageConverters(this.messageConverters);
if (this.messageConverters.isEmpty()) {
// 如果上面没有添加消息转换器,这里添加默认的消息转换器
addDefaultHttpMessageConverters(this.messageConverters);
}
// 这里就是调用DelegatingWebMvcConfiguration重写的方法,扩展消息转化器
extendMessageConverters(this.messageConverters);
}
return this.messageConverters;
}
加载jackson里的类,能加载成功jackson2Present返回true,不能加载成功,表示没有这个类,没有导入包,返回jackson2Present返回false,然后去判断是否导入Google、JDK自带的处理JSON类。一般我们会导入**Jackson
**,那么这里会添加**MappingJackson2HttpMessageConverter
**消息转换器。
// WebMvcConfigurationSupport类方法
protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
// 默认消息转换器
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new ResourceRegionHttpMessageConverter());
...
// jackson
if (jackson2Present) {
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}
// Google Gson 库中的一个核心类,Java对象与JSON 格式字符串进行相互转换
else if (gsonPresent) {
messageConverters.add(new GsonHttpMessageConverter());
}
// JDK 类库JSON类
else if (jsonbPresent) {
messageConverters.add(new JsonbHttpMessageConverter());
}
...
}
RequestMappingHandlerAdapter的类图如下(有删减)
与RequestMappingHandlerMapping一样,RequestMappingHandlerAdapter对象初始化就会调用**InitializingBean接口
**的**afterPropertiesSet
**方法来**实现初始化
**。
// RequestMappingHandlerAdapter类方法
@Override
public void afterPropertiesSet() {
// 初始化@ControllerAdvice
initControllerAdviceCache();
// 设置默认的方法参数解析器
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
// 设置默认的返回值处理器
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
@ControllerAdvice
**注解的beanControllerAdviceBean
**,添加到集合中RequestBodyAdvice
**或**ResponseBodyAdvice
**的bean对象 前后
**做一些**扩展
**处理// RequestMappingHandlerAdapter类方法
private void initControllerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
// 获取所有@ControllerAdvice注解的bean,创建成ControllerAdviceBean对象的集合
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
...
// 筛选实现RequestBodyAdvice或ResponseBodyAdvice的adviceBean
if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
}
}
if (!requestResponseBodyAdviceBeans.isEmpty()) {
this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
}
...
}
public static List<ControllerAdviceBean> findAnnotatedBeans(ApplicationContext context) {
ListableBeanFactory beanFactory = context;
if (context instanceof ConfigurableApplicationContext) {
beanFactory = ((ConfigurableApplicationContext) context).getBeanFactory();
}
List<ControllerAdviceBean> adviceBeans = new ArrayList<>();
// 遍历所有的bean对象
for (String name : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Object.class)) {
if (!ScopedProxyUtils.isScopedTarget(name)) {
// 寻找有@ControllerAdvice注解
ControllerAdvice controllerAdvice = beanFactory.findAnnotationOnBean(name, ControllerAdvice.class);
if (controllerAdvice != null) {
// 创建ControllerAdviceBean对象添加到集合中
adviceBeans.add(new ControllerAdviceBean(name, beanFactory, controllerAdvice));
}
}
}
OrderComparator.sort(adviceBeans);
return adviceBeans;
}
RequestBodyAdvice请求增强器
public interface RequestBodyAdvice {
// 是否支持,自定义判断条件,如包含某个自定义注解等等
// 该方法返回true时,才会进去下面的beforeBodyRead方法
boolean supports(MethodParameter methodParameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType);
// 请求体解析前处理,一般在此方法中对body数据进行修改
HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException;
// 请求体解析后处理,一般直接返回原实例
Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
// 当body为empty时操作(body什么都不传才算,即使{}也不算空)
@Nullable
Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
}
ResponseBodyAdvice响应增强器
public interface ResponseBodyAdvice<T> {
// 是否支持,自定义判断条件
// 该方法返回true时,才会进去下面的 beforeBodyWrite方法
boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
// 响应写入之前调用
@Nullable
T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response);
}
public interface HandlerMethodArgumentResolver {
/**
* 此解析器是否支持给定的方法参数
*/
boolean supportsParameter(MethodParameter parameter);
/**
* 将方法参数解析为给定请求的参数值
*/
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}
public interface HandlerMethodReturnValueHandler {
/**
* 此处理程序是否支持给定的方法返回类型
*/
boolean supportsReturnType(MethodParameter returnType);
/**
* 通过向模型添加属性并设置视图或设置
*/
void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}
RequestResponseBodyMethodProcessor
**类既是**@RequestBody
**解析器又是**@ResponseBody
**解析器**对应方法参数解析器和返回值处理器这里就不展开说了,只要知道项目启动会加载这些东西即可,下一篇文章请求的执行流程再进入源码研究。
与消息转换器很像,先遍历所有WebMvcConfigurer实现类configureHandlerExceptionResolvers中**新增
**的异常处理器,如果没有开发者或者第三方新增,那么添加默认的的异常处理器,再调用扩展方法,也就是遍历所有WebMvcConfigurer实现类,调用他们的extendHandlerExceptionResolvers方法,对异常处理器做最后**修改
**。
// WebMvcConfigurationSupport类方法
@Bean
public HandlerExceptionResolver handlerExceptionResolver(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
// 创建空集合
List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();
// 这里就是调用DelegatingWebMvcConfiguration重写的方法
// 其实就是寻找WebMvcConfigurer实现类是否添加异常处理器
configureHandlerExceptionResolvers(exceptionResolvers);
if (exceptionResolvers.isEmpty()) {
addDefaultHandlerExceptionResolvers(exceptionResolvers, contentNegotiationManager);
}
// 这里就是调用DelegatingWebMvcConfiguration重写的方法,扩展异常处理器
extendHandlerExceptionResolvers(exceptionResolvers);
HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
composite.setOrder(0);
composite.setExceptionResolvers(exceptionResolvers);
return composite;
}
包含
**所有的自定义异常处理器 protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers,
ContentNegotiationManager mvcContentNegotiationManager) {
// 这个异常处理器内包含所有的自定义异常处理器
ExceptionHandlerExceptionResolver exceptionHandlerResolver = createExceptionHandlerExceptionResolver();
exceptionHandlerResolver.setContentNegotiationManager(mvcContentNegotiationManager);
exceptionHandlerResolver.setMessageConverters(getMessageConverters());
exceptionHandlerResolver.setCustomArgumentResolvers(getArgumentResolvers());
exceptionHandlerResolver.setCustomReturnValueHandlers(getReturnValueHandlers());
if (jackson2Present) {
exceptionHandlerResolver.setResponseBodyAdvice(
Collections.singletonList(new JsonViewResponseBodyAdvice()));
}
if (this.applicationContext != null) {
exceptionHandlerResolver.setApplicationContext(this.applicationContext);
}
// 手动调用初始化接口的初始化方法
exceptionHandlerResolver.afterPropertiesSet();
exceptionResolvers.add(exceptionHandlerResolver);
// ResponseStatus异常处理器
ResponseStatusExceptionResolver responseStatusResolver = new ResponseStatusExceptionResolver();
responseStatusResolver.setMessageSource(this.applicationContext);
exceptionResolvers.add(responseStatusResolver);
// 默认异常处理器
exceptionResolvers.add(new DefaultHandlerExceptionResolver());
}
// ExceptionHandlerExceptionResolver类方法
@Override
public void afterPropertiesSet() {
// 初始化异常处理增强类
initExceptionHandlerAdviceCache();
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
@ControllerAdvice
**类且方法上存在**@ExceptionHandler
**// ExceptionHandlerExceptionResolver类方法
private void initExceptionHandlerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
// 获取所有@ControllerAdvice注解的bean,创建成ControllerAdviceBean,添加到集合中
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
// 筛选方法上@ExceptionHandler注解
ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);
if (resolver.hasExceptionMappings()) {
this.exceptionHandlerAdviceCache.put(adviceBean, resolver);
}
if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
this.responseBodyAdvice.add(adviceBean);
}
}
}
// ExceptionHandlerMethodResolver类属性和方法
public static final MethodFilter EXCEPTION_HANDLER_METHODS = method ->
AnnotatedElementUtils.hasAnnotation(method, ExceptionHandler.class);
public ExceptionHandlerMethodResolver(Class<?> handlerType) {
for (Method method : MethodIntrospector.selectMethods(handlerType, EXCEPTION_HANDLER_METHODS)) {
for (Class<? extends Throwable> exceptionType : detectExceptionMappings(method)) {
addExceptionMapping(exceptionType, method);
}
}
}
至此,SpringMVC启动重要的组件都介绍完毕。
AbstractAnnotationConfigDispatcherServletInitializer
**的MVC配置类(开发者创建,**代替web.xml
**)DispatcherServlet的映射路径
**,**注册过滤器
**创建web注解容器
**、**创建DispatcherServlet对象
**、**添加过滤器
**到Tomcat容器的过滤器集合中 @Controller
**注解的bean配置拦截器
**、**消息转换器
**的等配置,只要实现**WebMvcConfigurer
**接口重写对应方法即可@RequestMapping
**注解(根据注解属性创建对象RequestMappingInfo) 类上
**是否有**@Controller
**或**@RequestMapping
**注解的bean方法上
**是否有**@RequestMapping
**注解两个map
**存起来,以后映射方法从这里获取 pathLookup
@RequestMapping
**注解的**映射路径
**RequestMappingInfo
**对象registry
RequestMappingInfo
**对象MappingRegistration
**对象(包含Controller#Method)@ControllerAdvice
**注解 类上
**有**@ControllerAdvice
**注解的bean RequestBodyAdvice
**或**ResponseBodyAdvice
**,那就是请求响应数据增强器@ExceptionHandler
**,那就是异常处理器