层层递进的关系来分析SpringBoot的部分源码
1. SpringBoot 静态资源源码分析
2. SpringBoot 请求处理源码分析
3. SpringBoot 响应处理源码分析
4. SpringBoot 视图解析器源码分析
一、 静态资源访问 1. 静态资源目录只要放在类路径下:called /static(or /public or /resources or /meta-INF/resources) 访问当前项目路径/ + 静态资源名,只需要写静态资源名就能访问,springboot
原理:/**
收到请求后先去匹配 controller,如果不能处理就去交给静态资源处理器。
改变默认的静态资源位置
web:
resources:
static-locations: classpath:/path
2. 静态资源访问前缀
spring:
mvc:
static-path-pattern: /res/**
当前项目 + static-path-pattern + 静态资源名 = 静态资源文件夹下的
二、欢迎页支持 1. 自动加载的欢迎页面- 在静态资料路径下 index.html
- 可以配置静态资源路径
- 但是不可以配置静态资源的访问前缀。否则导致index.html 不能被默认访问
- controller 能够处理 /index 请求的controller 自动会请求
将 favicon.ico 放置在静态资源路径下,会自动将favicon.ico 作为页面小图标
三、静态资源配置原理 1. 加载配置类源码- springboot启动默认加载 XXXAutoConfiguration类(自动配置类)
- SpringMVC功能的自动配置类是 WebMvcAutoConfiguration
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {}
2. 配置类生效源码
@Configuration(
proxyBeanMethods = false
)
@import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class, WebProperties.class})
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {}
配置文件的相关属性和什么进行了绑定
如果配置中只有一个有参构造器,那么属性会自动从容器中找
// ResourceProperties 获取 spring.resources
// WebMvcProperties 获取 sprint.mvc
// ListableBeanFactory 获取bean 工厂
// ResourceHandlerRegistrationCustomizer 获取资源处理自定义器
// ...
public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider messageConvertersProvider, ObjectProvider resourceHandlerRegistrationCustomizerProvider, ObjectProvider dispatcherServletPath, ObjectProvider> servletRegistrations) {
this.resourceProperties = (Resources)(resourceProperties.hasBeenCustomized() ? resourceProperties : webProperties.getResources());
this.mvcProperties = mvcProperties;
this.beanFactory = beanFactory;
this.messageConvertersProvider = messageConvertersProvider;
this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
this.dispatcherServletPath = dispatcherServletPath;
this.servletRegistrations = servletRegistrations;
this.mvcProperties.checkConfiguration();
}
3. 资源处理的默认规则源码
这样可以看出默认规则下的SpringBoot 以什么路径作为静态资源,以及为webjar的配置
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/meta-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
}
4. 可以直接禁用所有静态资源
spring:
web:
resources:
add-mappings: false
5. 默认资源配置源码
private static final String[] CLASSPATH_RESOURCE_LOCATIONS =
new String[]{"classpath:/meta-INF/resources/",
"classpath:/resources/", "classpath:/static/",
"classpath:/public/"};
private String[] staticLocations;
private boolean addMappings;
private final ResourceProperties.Chain chain;
private final ResourceProperties.Cache cache;
6. 欢迎页源码分析
我们都知道SpringBoot中有默认的欢迎页面,这里是用SpringBoot给我们提供的类 WelcomePageHandlerMapping 来进行提供的,在访问这个HanderMapping之前,其实SpringBoot 会先去访问 RequestMappingHandlerMapping,即程序员自己创建的 controller 的HandlerMapping,这也说明了我们编写的Controller的优先级是最高的(后面有详细描述)。
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
return welcomePageHandlerMapping;
}
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {
if (welcomePage != null && "/**".equals(staticPathPattern)) {
logger.info("Adding welcome page: " + welcomePage);
this.setRootViewName("forward:index.html");
}
else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
logger.info("Adding welcome page template: index");
this.setRootViewName("index");
}
}



