简介
SpringBoot是用来简化Spring应用的初始搭建和开发过程的新框架,该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置;它内置Tomcat或Jetty等Servlet容器,并提供自动配置的“starter”项目对象模型以简化Maven配置.
SpringBoot框架有两个重要的策略:开箱即用和约定优于配置。
-
开箱即用:指在开发过程中,通过在MAVEN项目的pom文件中添加相关依赖包,然后使用对应注解来代替繁琐的XML配置文件以管理对象的生命周期。
-
约定优于配置:通过约定来减少配置。框架应假定合理默认值(在大部分情况下,你会发现使用框架提供的默认值会让你的项目开发起来效率更快)。
比如当我们导入一个 spring-boot-starter-web 后,就约定我们是在一个web开发环境,然后自动帮我们导入 Spring MVC 的相关依赖。(而不是Struct2之类的)
第一个SpringBoot
本例的SpringBoot版本为2.2.0,IDEA版本2019.3.1

创建后的项目结构为:

依赖文件:
<?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.on1</groupId>
<artifactId>springbootMaaven</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- 这个插件,可以将应用打包成一个可执行的jar包;-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
在maven的安装目录的settings.xml文件夹下添加阿里云镜像:
<mirrors>
<!-- 阿里云镜像 -->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
类:
package com.on1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/halo")
public String hello() {
return "hello world";
}
}
运行MainApplication程序后,访问 http://localhost:8080/hello


我们还可以将整个工程打包:点击pachage

然后就会可以多出的打包的jar包

Spring Initializer
IDE支持使用Spring的项目创建向导来快速创建一个SpringBoot项目,创建步骤如下:



完成后的项目结构图如下:

删除掉.gitignore,mvnw,mvnw.cmd后,将原来项目的两个类拷贝进来:

解释一下resources文件夹的目录结构:
- static:保存所有的静态资源,如js css images;
- templates:保存所有模板页面,可以使用模板引擎
- application.properties:SpringBoot应用的配置文件,可以修改一下默认配置。比如可以通过server.port=8081来修改端口
简介流程
相关依赖
在前面我们往项目里的pom.xml导入了一个父项目依赖:
<parent>
<!-- 项目的父工程是org.springframework.boot-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath/>
</parent>
而org.springframework.boot也有一个父项目,
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
之后我们导入的spring-boot相关依赖默认不需要写版本。
然后我们导入了一个依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
spring-boot-starter是一个场景启动器,它帮我们导入了web模块正常运行所依赖的组件。如果我们希望某些特定功能,比如redis,只需在项目里引入这些starter相关场景的依赖即可。

主程序类
//该注解表示该类是主配置类,通过运行该方法启动SpringBoot应用。
@SpringBootApplication
public class HaloworldQuickstartApplication {
public static void main(String[] args) {
SpringApplication.run(HaloworldQuickstartApplication.class, args);
}
}
SpringBootApplication注解
@Target({ElementType.TYPE}) //可以给一个类型进行注解,比如类、接口、枚举
//可以保留到程序运行的时候,它会被加载进入到 JVM 中
@Retention(RetentionPolicy.RUNTIME)
@Documented //将注解中的元素加入文档javadoc中
@Inherited //被该注解注释的类的子类也会拥有注解@SpringBootTest
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@SpringBootConfiguration注解
该注解标注的类表示是一个SpringBoot的配置类
@Configuration
public @interface SpringBootConfiguration {
}
@EnableAutoConfiguration注解
该注解负责开启自动配置功能
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage注解
该注解负责将主配置类的所在包(本例的com.on1.haloworldquickstart)及下面所有子包里面的所有组件扫描到Spring容器
// Spring底层注解@Import负责给容器导入组件
// 导入的组件由Registrar类指定
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}
@Import({AutoConfigurationImportSelector.class})
点进AutoConfigurationImportSelector类。搜索方法public String[] selectImports()。 其中configurationss数组是容器中需要导入的组件,此处我们通过debug来看一下数组的值:

这些组件名都是类似xxxAutoConfiguration的形式,即自动配置类。因此 AutoConfigurationImportSelector类会往容器里导入许多的自动配置类,这样就避免了我们手动编写配置注入功能组件等的工作。
自动配置类从何得来?
由上图可看出是通过getCandidateConfigurations()方法来获取候选配置文件,

该方法的第一个参数值是EnableAutoConfiguration.class,第二个参数则是类加载器classLoader。
该方法负责从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,比如下图:

它将这些值作为自动配置类导入容器中,这样自动配置类就会生效,从而帮我们进行自动配置工作。
以 HttpEncodingAutoConfiguration类为例,该类负责Http编码的自动配置。
@Configuration //这是一个配置类
//将配置文件的值与HttpEncodingProperties绑定
@EnableConfigurationProperties({HttpEncodingProperties.class})
//基于Spring底层Condition注解,若当前应用是Web应用,则整个配置类里的配置就生效
@ConditionalOnWebApplication
//判断当前项目有无过滤器类CharacterEncodingFilter
@ConditionalOnClass({CharacterEncodingFilter.class})
//判断配置文件中是否存在某个配置(不存在则判断也是成立的)
@ConditionalOnProperty(
prefix = "spring.http.encoding",
value = {"enabled"},
matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
//封装了配置文件的相关属性的配置类,通过这个配置对象来从容器里取出想要的组件
private final Encoding properties;
@Bean
@ConditionalOnMissingBean({CharacterEncodingFilter.class})
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
return filter;
}
// 省略其他属性及方法
}
//从配置文件中获取指定值与bean属性进行绑定
//我们能配置属性都是来源于这些xxxProperties,
//比如我们可以主配置文件里配置:
// spring.http.encoding.charset=utf-8
// spring.http.encoding.force=true
// spring.http.encoding.enabled=true
@ConfigurationProperties(
prefix = "spring.http.encoding"
)
public class HttpProperties {
public static class Encoding {
public static final Charset DEFAULT_CHARSET;
private Charset charset;
private Boolean force;
// 省略其他属性及方法
}
}
@Conditional派生注解
前面我们看到了许多@Conditional的扩展注解,下图是其扩展注解及作用。

@Conditional注解表示必须是@Conditional派生注解指定的条件成立,才往容器里添加组件,配置类里的所有内容才能生效。
查看哪些自动配置类生效
我们可以在主配置文件中添加语句:
debug=true
来让控制台打印自动配置报告。成功匹配的配置类如下图所示

没有成功匹配的配置类如下图所示:
