目录
一、代码位置
二、统一版本管理(parent)
三、提供 starter简化 Maven 配置
四、自动配置 Spring(引导类)
五、嵌入式 servlet 容器
一、代码位置
二、统一版本管理(parent)
SpringBoot项目都会继承一个父依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.4</version><relativePath/> <!-- lookup parent from repository --></parent>
parent 自身具有很多个版本,每个 parent 版本中包含有几百个其他技术的版本号,不同的parent间使用的各种
技术的版本号有可能会发生变化。当开发者使用某些技术时,直接使用SpringBoot提供的 parent 就行了,由
parent 帮助开发者统一的进行各种技术的版本管理整体上来说,使用parent可以帮助开发者进行版本的统一管
理。项目中的pom.xml中继承了一个坐标
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.4</version>
</parent>
打开后可以查阅到其中又继承了一个坐标
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.5.4</version>
</parent>
这个坐标中定义了两组信息第一组是各式各样的依赖版本号属性,下面列出依赖版本属性的局部,可以看的出
来,定义了若干个技术的依赖版本号。
<properties><activemq.version>5.16.3</activemq.version><aspectj.version>1.9.7</aspectj.version><assertj.version>3.19.0</assertj.version><commons-codec.version>1.15</commons-codec.version><commons-dbcp2.version>2.8.0</commons-dbcp2.version><commons-lang3.version>3.12.0</commons-lang3.version><commons-pool.version>1.6</commons-pool.version><commons-pool2.version>2.9.0</commons-pool2.version><h2.version>1.4.200</h2.version><hibernate.version>5.4.32.Final</hibernate.version><hibernate-validator.version>6.2.0.Final</hibernate-validator.version><httpclient.version>4.5.13</httpclient.version><jackson-bom.version>2.12.4</jackson-bom.version><javax-jms.version>2.0.1</javax-jms.version><javax-json.version>1.1.4</javax-json.version><javax-websocket.version>1.1</javax-websocket.version><jetty-el.version>9.0.48</jetty-el.version><junit.version>4.13.2</junit.version>
</properties>
第二组是各式各样的依赖坐标信息,可以看出依赖坐标定义中没有具体的依赖版本号,而是引用了第一组信息中
定义的依赖版本属性值
<dependencyManagement><dependencies><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>${hibernate.version}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version></dependency></dependencies>
</dependencyManagement>
上面的依赖坐标定义是出现在标签中的,是对引用坐标的依赖管理,并不是实际使用的坐标。
因此当我们项目中继承了这组parent信息后,在不使用对应坐标的情况下,前面的这组定义是不会具体导入某个
依赖的。因为在maven中继承机会只有一次,上述继承的格式还可以切换成导入的形式进行。
<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
三、提供 starter简化 Maven 配置
starter定义了使用某种技术时对于依赖的固定搭配格式,也是一种最佳解决方案,使用starter可以帮助开发者减
少依赖配置。项目中的pom.xml定义了使用SpringMVC技术,但是并没有写SpringMVC的坐标,而是添加了一
个名字中包含starter的依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
在spring-boot-starter-web中又定义了若干个具体依赖的坐标
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.5.4</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId><version>2.5.4</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><version>2.5.4</version><scope>compile</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.3.9</version><scope>compile</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.9</version><scope>compile</scope></dependency>
</dependencies>
以 spring-boot-starter-json 为例,看看 starter 里面装的是什么?
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.5.4</version><scope>compile</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.3.9</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.4</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jdk8</artifactId><version>2.12.4</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>2.12.4</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.module</groupId><artifactId>jackson-module-parameter-names</artifactId><version>2.12.4</version><scope>compile</scope></dependency>
</dependencies>
可以发现,这个starter中又包含了若干个坐标,其实就是使用SpringMVC开发通常都会使用到Json,使用json又
离不开这里面定义的这些坐标,SpringBoot都给我们整合好了。
从而,得到了一个信息,使用starter可以帮开发者快速配置依赖关系。
以前写依赖3个坐标的,现在导入一个就搞定,极大的加速了依赖配置。
谨记:
所有的starter中都会依赖下面这个starter,叫做spring-boot-starter。
这个starter是所有的SpringBoot的starter的基础依赖,里面定义了SpringBoot相关的基础配置
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.5.4</version><scope>compile</scope>
</dependency>
四、自动配置 Spring(引导类)
@SpringBootApplication
public class Springboot0101QuickstartApplication {public static void main(String[] args) {SpringApplication.run(Springboot0101QuickstartApplication.class, args);}
}
SpringBoot本身是为了加速Spring程序的开发的,而Spring程序运行的基础是需要创建Spring容器对象(IoC容
器)并将所有的对象放置到Spring容器中管理,也就是一个一个的Bean。
改用 SpringBoot 就是为了加速开发Spring程序,当引导类运行后就会产生一个Spring容器对象,并且可以将这
个对象保存起来,通过容器对象直接操作Bean。
伪代码如下:
@SpringBootApplication
public class Springboot0101QuickstartApplication {public static void main(String[] args) {ConfigurableApplicationContext ctx = SpringApplication.run(Springboot0101QuickstartApplication.class, args);BookController bean = ctx.getBean(BookController.class);System.out.println("bean======>" + bean);User user = ctx.getBean(User.class);System.out.println(user);}}
通过上述操作不难看出,其实SpringBoot程序启动还是创建了一个Spring容器对象。
当前运行的这个类在SpringBoot程序中是所有功能的入口,称为引导类。
作为一个引导类最典型的特征就是当前类上方声明了一个注解@SpringBootApplication。
五、嵌入式 servlet 容器
当前我们做的SpringBoot入门案例勾选了Spring-web的功能,并且导入了对应的starter。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
要做web程序,肯定离不开使用web服务器,SpringBoot内置的web服务器帮我们减少了 Tomcat 的配置,打开
web对应的starter查看导入了哪些东西。
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.5.4</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId><version>2.5.4</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><version>2.5.4</version><scope>compile</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.3.9</version><scope>compile</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.9</version><scope>compile</scope></dependency>
</dependencies>
第三个依赖就是tomcat对应的东西了,也有一个starter,打开看看。
<dependencies><dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>1.3.5</version><scope>compile</scope></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>9.0.52</version><scope>compile</scope><exclusions><exclusion><artifactId>tomcat-annotations-api</artifactId><groupId>org.apache.tomcat</groupId></exclusion></exclusions></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-el</artifactId><version>9.0.52</version><scope>compile</scope></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-websocket</artifactId><version>9.0.52</version><scope>compile</scope><exclusions><exclusion><artifactId>tomcat-annotations-api</artifactId><groupId>org.apache.tomcat</groupId></exclusion></exclusions></dependency>
</dependencies>
里面有一个核心的坐标,tomcat-embed-core,叫做tomcat内嵌核心。
就是这个东西把tomcat功能引入到了我们的程序中的。目前解决了第一个问题,找到根儿,那么谁把tomcat引入
到程序中的?
经过发现,是spring-boot-starter-web中的spring-boot-starter-tomcat做的。
居然什么都不做,就有了web服务器对应的功能。再来说第二个问题,这个服务器是怎么运行的。
内嵌Tomcat运行原理
Tomcat服务器是一款软件,而且是一款使用java语言开发的软件,熟悉tomcat的话应该知道tomcat安装目录中
保存有很多jar文件。既然是使用java语言开发的,运行的时候肯定符合java程序运行的原理,java程序运行靠的是
什么?对象呀,一切皆对象,万物皆对象。那tomcat运行起来呢?也是对象。
Spring容器就是用来管理对象的,这个对象能交给Spring容器管理,tomcat服务器自然而然就运行起来了,
Tomcat 运行其实就是以对象的形式在Spring容器中运行的。
<dependencies><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>9.0.52</version><scope>compile</scope></dependency>
</dependencies>
既然是个对象,如果把这个对象从Spring容器中去掉就说明会没有web服务器的功能。
可以通过依赖排除的方式去掉这个web服务器功能。
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency>
</dependencies>
除了通过依赖排除的方式去掉这个web服务器功能,还可以更改 Servlet 容器。
其实,SpringBoot提供了3款内置的服务器:
- tomcat(默认):apache出品,粉丝多,应用面广,负载了若干较重的组件
- jetty:更轻量级,负载性能远不及tomcat
- undertow:负载性能勉强跑赢tomcat
想用哪个,加个坐标就行。前提是要把默认的 tomcat 排除掉,因为tomcat是默认加载的。
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId></dependency>
</dependencies>