自动配置
在pom.xml中有一个parent
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
而在spring-boot-starter-parent中还有一个parent:spring-boot-dependencies
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.3</version>
</parent>
其中包含了大量的核心依赖,我们在我们在导入一些springboot依赖时不需要指明版本号便是因为在spring-boot-dependencies已经声明了
启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.4.3</version>
<scope>compile</scope>
</dependency>
即springboot 的启动场景 如导入spring-boot-starter-web,便会帮我们导入所需的所有web依赖 需要什么只需导入对应的starter即可
主程序
//主程序入口
//标注为springboot程序
@SpringBootApplication
public class SpringBoot01Application {
public static void main(String[] args) {
//将程序启动
SpringApplication.run(SpringBoot01Application.class, args);
}
}
@SpringBootConfiguration
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {}
在@SpringBootApplication有两个注解@SpringBootConfiguration 和@EnableAutoConfiguration
在@SpringBootConfiguration有一个@Configuration 指明这是一个配置类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {}
而在@Configuration中有@Component 指明这是一个组件
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {}
@EnableAutoConfiguration(自动配置)
// @EnableAutoConfiguration:自动配置注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
在@EnableAutoConfiguration中有AutoConfigurationPackage和 Import(AutoConfigurationImportSelector.class) 两个注解
@AutoConfigurationPackage
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}
@Import(AutoConfigurationPackages.Registrar.class)导入自动注册包 给容器批量导入一些组件
@Import(AutoConfigurationImportSelector.class)
获取需要导入的配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
利用工厂加载所有需要的组件
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader)
默认从META-INF/spring.factories扫描需要加载的组件
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
web静态资源导入
1.WebMVcAutoConfiguration.java中有这么一段代码
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class,
org.springframework.boot.autoconfigure.web.ResourceProperties.class, WebProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
通过点击WebMvcProperties.class进入对应的类
@EnableConfigurationProperties({ WebMvcProperties.class,...)
发现
/**
* Path pattern used for static resources.
*/
private String staticPathPattern = "/**";
因此获得了静态资源加载的第一个路径
- webjars 在WebMVcAutoConfiguration.java中有这么一个函数
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
//如果有指明映射则提示默认配置失效
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
ServletContext servletContext = getServletContext();
//如果导入有webjars则从classpath:/META-INF/resources/webjars/开始加载静态资源否则返回空
addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
//如果没有导入webjars,则从this.resourceProperties.getStaticLocations()开始加载静态资源
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (servletContext != null) {
registration.addResourceLocations(new ServletContextResource(servletContext, SERVLET_LOCATION));
}
});
}
因此我们获得了静态资源加载的第二个路径:classpath:/META-INF/resources/webjars/,将其加载到了/webjars/** 下
3.在上面的代码中有这么一段
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
这其中this.mvcProperties.getStaticPathPattern()便是获取我们第一个得到的路径 /**
通过点击getStaticLocations()获得
public String[] getStaticLocations() {
return this.staticLocations;
}
再次点击staticLocations得到
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
最终我们获得
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
"classpath:/resources/", "classpath:/static/", "classpath:/public/" };
这是我们获取的第三个静态资源加载路径,并且是将其加载到了/** 下
总结:
classpath:/META-INF/resources/webjars/ 映射到 localhost:8080/webjars/
public static /** resources 映射到 localhost:8080/
优先级:resource>static(默认)>public
我们可以通过spring.mvc.static-path-pattern= /hello/**,classpath:/line/
来修改默认的地址
首页
WebMVcAutoConfiguration.java中有这么一段代码
private Resource getWelcomePage() {
//遍历静态资源目录
for (String location : this.resourceProperties.getStaticLocations()) {
Resource indexHtml = getIndexHtml(location);
//成功获取index.html并返回
if (indexHtml != null) {
return indexHtml;
}
}
ServletContext servletContext = getServletContext();
if (servletContext != null) {
return getIndexHtml(new ServletContextResource(servletContext, SERVLET_LOCATION));
}
return null;
}