Spring Boot是Spring开源组织下的子项目,是Spring组件一站式解决方案,主要是简化了使用Spring的难度,简省了繁重的配置,提供了各种启动器。Spring Boot 不需要独立的容器运行,内置了 Tomcat/ Jetty 等容器
优点
- 独立运行
Spring Boot而且内嵌了各种servlet容器,Tomcat、Jetty等,现在不再需要打成war包部署到容器中,Spring Boot只要打成一个可执行的jar包就能独立运行,所有的依赖包都在一个jar包内。 - 简化配置
spring-boot-starter-web启动器自动依赖其他组件,简少了maven的配置。 - 自动配置
Spring Boot能根据当前类路径下的类、jar包来自动配置bean,如添加一个spring-boot-starter-web启动器就能拥有web的功能,无需其他配置。 - 无代码生成和XML配置
Spring Boot配置过程中无代码生成,也无需XML配置文件就能完成所有配置工作,这一切都是借助于条件注解完成的,这也是Spring4.x的核心功能之一。 - 应用监控
Spring Boot提供一系列端点可以监控服务及应用,做健康检测。 - @ImportResource 注解导入老 Spring 项目配置文件
Spring Boot中的监视器
Spring boot actuator是spring启动框架中的重要功能之一。Spring boot监视器可帮助您访问生产环境中正在运行的应用程序的当前状态。
有几个指标必须在生产环境中进行检查和监控。即使一些外部应用程序可能正在使用这些服务来向相关人员触发警报消息。监视器模块公开了一组可直接作为HTTP URL访问的REST端点来检查状态
Spring Boot 的核心配置文件以及区别
在 Spring Boot 中有两种上下文,一种是 bootstrap, 另外一种是 application, bootstrap 是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。bootstrap 主要用于从额外的资源来加载配置信息,还可以在本地外部配置文件中解密属性。这两个上下文共用一个环境,它是任何Spring应用程序的外部属性的来源。bootstrap 里面的属性会优先加载,它们默认也不能被本地相同配置覆盖。
因此,对比 application 配置文件,bootstrap 配置文件具有以下几个特性。
- boostrap 由父 ApplicationContext 加载,比 applicaton 优先加载
- boostrap 里面的属性不能被覆盖
- application 配置文件这个容易理解,主要用于 Spring Boot 项目的自动化配置。
- bootstrap 配置文件有以下几个应用场景。
使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息;
一些固定的不能被覆盖的属性;
一些加密/解密的场景;
核心注解
启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:
@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能:
@ComponentScan:Spring组件扫描。
Spring Boot 自动配置原理
Spring Boot的自动配置注解是@EnableAutoConfiguration,
@Configuration,@ConditionalOnClass就是自动配置的核心,首先它得是一个配置文件,其次根据类路径下是否有这个类去自动配置。
- 查看自动配置报告
怎么查看自己加的自动配置类有没有被加载,或者查看所有自动配置激活的和未激活的可以通过以下几种试查看。
spring-boot:run运行的在对话框Enviroment中加入debug=true变量
java -jar xx.jar --debug
main方法运行,在VM Argumanets加入-Ddebug
直接在application文件中加入debug=true
如果集成了spring-boot-starter-actuator监控,通过autoconfig端点也可以查看。
Positive matches:已经启用的自动配置
Negative matches:未启用的自动配置 - Starters
Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring 及其他技术,而不需要到处找示例代码和依赖包。如你想使用 Spring JPA 访问数据库,只要加入 spring-boot-starter-data-jpa 启动器依赖就能使用了。
Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖 - 在 Spring Boot 启动的时候运行一些特定的代码
可以实现接口 ApplicationRunner 或者 CommandLineRunner,这两个接口实现方式一样,它们都只提供了一个 run 方法 - Spring Boot 读取配置的方式
Spring Boot 可以通过 @PropertySource,@Value,@Environment, @ConfigurationProperties 来绑定变量
前期准备
修改bom.xml
<!--spring boot父节点依赖,引入这个之后相关的引入就不需要添加version配置,spring boot 会自动选择最合适的版本进行添加 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELESE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--指定编译版本-->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- 指定jdk版本,默认是1.6-->
<java.version>1.8</java.version>
<properties>
<dependencies>
<!-- spring-boot-stsrter-web:提供了MVC,AOP......的依赖包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-stsrter-web</artifactId>
</dependency>
<!--基于spring的版本-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
</dependencies>
简单构建
- 创建Controller
@RestController(等价于@Controller和@responseBody)
public class MyController
{
//建立请求映射
@RequestMapping("/hello")
public void say() { }
}
- 编写启动类
spring boot 默认情况下可以扫描到的是@SpringBootApplication所在的类的同包或者子包下的类
@SpringBootApplication
public class App{
public static void main(string [] args){
SpringApplication.run(App.class,args);
}
}
spring Boot热部署(springLoader)
- 在pom.xml中添加配置信息即可(这个只有在修改返回值时有用,新增的映射路径则不行)
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.4.RELEASE</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier> exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
spring-boot-devtools
作用:自动应用代码更改到最新的APP上面去,
原理:发现代码更改之后,重新启动应用。(深层原理是使用两个ClassLoad,一个ClassLoad加载那些不会改变的类(第三方jar包),另一个ClassLoad加载会更改的类。称为restart ClassLoad,这样在代码更改的时候,原来的restart ClassLoad被丢弃,重新创建一个新的,由于需要加载的类相对较少,所以实现了较快的重启时间(5秒以内))
- 使用方法
添加依赖包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtolls</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
- 添加spring-boot-maven-plugin
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--没有这个配置,devtools不会起作用,即应用不会restar-->
<fork>truw</fork>
</configuration>
</plugin>
</plugins>
</build>
全局异常捕获
spring boot 集成MyBatis
集成Mybatis,使用PageHelper,获取自增长ID
- 添加依赖
基本依赖,jdk版本号;
MySQL驱动,mybatis依赖包,mybatis分页PageHelper:
<!--mysql数据库驱动-->
<dependency>
<groupid>mysql</groupid>
<artifactld>mysql-connector-java</artifactld>
</dependency>
<!--spring boot mybatis 依赖-->
<dependency>
<groupid>org.mybatis.spring.boot</groupid>
<artifactld>mybatis-spring-boot-starter</artifactld>
<version>1.1.1</version>
</dependency>
<!--mybatis 提供了拦截器接口,-->
<dependency>
<groupid>com.github.pagehelper</groupid>
<artifactld>pagehelper</artifactld>
<version>4.1.1</version>
</dependency>
- 创建启动类
这里的启动类比以往多个注解@MapperScan(mapper所在的包路径)
优化
优化主要包括配置文件和JVM参数修改: springBoot项目优化
- application.properties
比较重要的有:
server.tomcat.max-connections=1000 # Maximum number of connections that the server accepts and processes at any given time.
server.tomcat.max-http-header-size=0 # Maximum size, in bytes, of the HTTP message header.
server.tomcat.max-http-post-size=0 # Maximum size, in bytes, of the HTTP post content.
server.tomcat.max-threads=0 # Maximum number of worker threads.
server.tomcat.min-spare-threads=20 # Minimum number of worker threads.
- JVM参数
-XX:MetaspaceSize=128m (元空间默认大小)
-XX:MaxMetaspaceSize=128m (元空间最大大小)
-Xms1024m (堆最大大小)
-Xmx1024m (堆默认大小)
-Xmn256m (新生代大小)
-Xss256k (棧最大深度大小)
-XX:SurvivorRatio=8 (新生代分区比例 8:2)
-XX:+UseConcMarkSweepGC (指定使用的垃圾收集器,这里使用CMS收集器)
-XX:+PrintGCDetails (打印详细的GC日志)
JDK8之后把-XX:PermSize 和 -XX:MaxPermGen移除了,取而代之的是
-XX:MetaspaceSize=128m (元空间默认大小)
-XX:MaxMetaspaceSize=128m (元空间最大大小)
JDK 8开始把类的元数据放到本地化的堆内存(native heap)中,这一块区域就叫Metaspace,中文名叫元空间。
使用本地化的内存有什么好处呢?最直接的表现就是java.lang.OutOfMemoryError: PermGen 空间问题将不复存在,因为默认的类的元数据分配只受本地内存大小的限制,也就是说本地内存剩余多少,理论上Metaspace就可以有多大,这解决了空间不足的问题。
不过,让Metaspace变得无限大显然是不现实的,因此我们也要限制Metaspace的大小:使用-XX:MaxMetaspaceSize参数来指定Metaspace区域的大小。JVM默认在运行时根据需要动态地设置MaxMetaspaceSize的大小。
启动远程debug
java -Djavax.net.debug=
ssl -Xdebug -Xnoagent -Djava.compiler=
NONE -Xrunjdwp:transport=
dt_socket,server=y,suspend=
n,address=8888 -jar springboot-1.0.jar
Spring Boot 中的 Tomcat 是如何启动的
我们直接点击run方法的源码,跟踪下来,发现最终的run方法是调用
ConfigurableApplicationContext方法
其实这个方法我们可以简单的总结下步骤为 > 1. 配置属性 > 2. 获取监听器,发布应用开始启动事件 > 3. 初始化输入参数 > 4. 配置环境,输出 banner > 5. 创建上下文 > 6. 预处理上下文 > 7. 刷新上下文 > 8. 再刷新上下文 > 9. 发布应用已经启动事件 > 10. 发布应用启动完成事件。
- 只要分析 Tomcat 内容的话,只需要关注两个内容即可,上下文是如何创建的,上下文是如何刷新的,分别对应的方法就是createApplicationContext() 和refreshContext(context),接下来我们来看看这两个方法做了什么。
protected ConfigurableApplicationContext createApplicationContext() {
Class<!--?--> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
这里就是根据我们的webApplicationType来判断创建哪种类型的 Servlet,代码中分别对应着 Web 类型(SERVLET),响应式 Web 类型(REACTIVE),非 Web 类型(default),我们建立的是Web类型,所以肯定实例化DEFAULT_SERVLET_WEB_CONTEXT_CLASS
指定的类,也就是
AnnotationConfigServletWebServerApplicationContext类,这个类继承的是ServletWebServerApplicationContext,这就是我们真正的主角,而这个类最终是继承了AbstractApplicationContext,了解完创建上下文的情况后,我们再来看看刷新上下文,相关代码如下
这里还是直接传递调用本类的refresh(context)方法,最后是强转成父类AbstractApplicationContext调用其refresh()方法,createWebServer()就是启动 Web 服务,但是还没有真正启动 Tomcat,既然webServer是通过ServletWebServerFactory来获取的.
总结
Spring Boot 的启动是通过new SpringApplication()实例来启动的,启动过程主要做如下几件事情:> 1. 配置属性 > 2. 获取监听器,发布应用开始启动事件 > 3. 初始化输入参数 > 4. 配置环境,输出banner > 5. 创建上下文 > 6. 预处理上下文 > 7. 刷新上下文 > 8. 再刷新上下文 > 9. 发布应用已经启动事件 > 10. 发布应用启动完成事件
而启动 Tomcat 就是在第7步中“刷新上下文”;Tomcat 的启动主要是初始化2个核心组件,连接器(Connector)和容器(Container),一个 Tomcat 实例就是一个 Server,一个 Server 包含多个 Service,也就是多个应用程序,每个 Service 包含多个连接器(Connetor)和一个容器(Container),而容器下又有多个子容器,按照父子关系分别为:Engine,Host,Context,Wrapper,其中除了 Engine 外,其余的容器都是可以有多个。