Spring Boot 快速入门

Spring Boot 概述

官网解释:

**Build Anything with Spring Boot:**Spring Boot is the starting point for building all Spring-based applications. Spring Boot is designed to get you up and running as quickly as possible, with minimal upfront configuration of Spring.

大概是说: Spring Boot 是所有基于 Spring 开发的项目的起点。Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件。

什么是 Spring Boot

Spring Boot 是基于所有 Spring 开发的项目的起点。Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件。简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架。

使用 Spring Boot 好处

回顾我们之前的 SSM 项目,搭建过程还是比较繁琐的,需要:

  1. 配置 web.xml,spring-mvc.xml,spring-mybatis.xml...
  2. 配置各种aven依赖,维护复杂的依赖关系。
  3. 配置数据库连接、配置日志文件
  4. 配置各配置文件的读取,开启注解

Spring Boot的出现可以有效改善这类问题,SpringBoot的宗旨并非要重写Spring或是替代Spring,而是希望通过设计大量的自动化配置等方式来简化Spring原有样板化的配置,使得开发者可以快速构建应用。

除了解决配置问题之外, Spring Boot还通过一系列StaiterPOMs的定义,让我们整合各项功能的时候,不需要在 Maven 的 pom.xml 中维护那些错综复杂的依赖关系,而是通过类似模块化的Starter模块定义来引用,使得依赖管理工作变得更为简单。

Spring Boot 自身就支持嵌入式的 Tomcat、 Jetty 等容器。所以,通过Spring Boot 构建的应用不再需要安装Tomcat,将应用打包成war,再部署到Tomcat 这样复杂的构建与部署动作,只需将Spring
Boot应用打成jar包,并通过java -jar命令直接运行就能启动一个标准化的Web应用,这使得Spring Boot应用变得非常轻便。

快速入门

创建 Spring Boot 项目不再阐述网上一大堆。

目录结构:

image-20200814161648923
  • src/main/java: 主程序入口 HelloApplication,可以通过直接运行该类来启动Spring Boot应用。

  • src/main/resources:配置目录,该目录用来存放应用的一些配置信息,比如应用名、服务端口、数据库链接等。由千我们引入了Web模块,因此产生了static目录与templates目录,前者用于存放静态资源,如图片、css、JavaScript等;后者用千存放Web页面的模板文件,这里我们主要演示提供RESTful APL所以这两个目录并不会用到。

  • src/test/:单元测试目录,生成的HelloApplicationTests通过JUnit 4实现,可以直接用运行Spring Boot应用的测试。

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.jacob</groupId>
    <artifactId>hello_world</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hello_world</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>

    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

在基础信息部分,groupid 和 artifactId 对应生成项目时页面上输入的内容。另外,我们还可以注意到,打包形式为 jar: <packaging>jar</packaging>,正如我们之前所介绍的,Spring Boot 默认将该 Web 应用打包为 jar 的形式,而非war 的形式,因为默认的Web模块依赖 会包含嵌入式的 Tomcat ,这样使得我们的应用jar自身就具备了提供Web服务的能力,后续我们会演示如何启动它。

父项目parent配置指定为 spring-boot-starter-parent 的 2.2.5.RELEASE 版本,该父项目中定义了Spring Boot版本的基础依赖以及一些默认配置内容,比如,配置文件 application.application 的位置等。

在项目依赖 dependencies 配置中, 包含了下面两项。

  • spring-boot-starter-web:全栈Web开发模块,包含嵌入式Tomcat、Spring MVC。

    image-20200814161825392
  • spring-boot-starter-test:通用测试模块,包含 JUnit、Hamcrest、Mockito。

    image-20200814161754000

这里所引用的 web 和 test 模块,在 Spring Boot 生态中被称为Starter POMs。Starter POMs是一系列轻便的依赖包,是一套一站式的 Spring 相关技术的解决方案。开发者在使用和整合模块时,不必再去搜寻样例代码中的依赖配置来复制使用,只需要引入对应的模块包即可。比如,开发Web应用的时候,就引入spring-boot-starter-web,希望应用具备访问数据库能力的时候,那就再引入 spring-boot-starter-jdbc 或是更好用的 spring-boot-starter-data-jpa。在使用 SpringBoot 构建应用的时候,各项功能模块的整合不再像传统 Spring 应用的开发方式那样,需要在 pom.xml 中做大量的依赖配置,而是通过使用Starter POMs定义的依赖包,使得功能模块整合变得非常轻巧,易于理解与使用。

Spring Boot 的 Starter POMs 采用 spring-boot-starter-* 的命名方式,*代表一个特别的应用功能模块,比如这里的web、test。

最后,项目构建的 build 部分,引入了 Spring Boot 的 Maven 插件,该插件非常实用,可以帮助我们方便地启停应用,这样在开发时就不用每次去找主类或是打包成jar来运行微服务, 只需要通过 mvn spring-boot:run 命令就可以快速启动 Spring Boot 应用。

实现RESTful API

在Spring Boot中创建一个 RESTful API 的实现代码同 Spring MVC 应用一样,只是不需要像 Spring MVC 那样先做很多配置,而是像下面这样直接开始编写Controller内容:

  • 新建package,命名为 com.jacob.hello.world.controller,可根据实际的构建情况修改成自己的路径。

  • 新建HelloController类,内容如下所示。

    @RestController
    public class HelloController {
        @RequestMapping("/hello")
        public String index(){
            return "hello";
        }
    }
  • 启动该应用,通过浏览器访问 http://localhost:8080/hello,我们可以看到返回了预期结果:Hello World。

编写单元测试

功能实现之后,我们要养成随手写配套单元测试的习惯,这在微服务架构中尤为重要。通常,我们实施微服务架构的时候,已经实现了前后端分离的项目与架构部署。那么在实现后端服务的时候,单元测试是在开发过程中用来验证代码正确性非常好的手段,并且这些单元测试将会很好地支持我们未来可能会进行的重构。

在 Spring Boot 中实现单元测试同样非常方便,下面我们打开 src/test/下的测试入口 com.jacob.hello.world.HelloWorldApplicationTests 类,编写一个简单的单元测试来模拟 HTTP 请求,测试之前实现的 /hello 接口,该接口应返回 hello 字符串。

@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloWorldApplicationTests {

    @Autowired
    private HelloController helloController;

    @Test
    public void contextLoads() {
        System.out.println(helloController.index());
    }

}
  • @RunWith(SpringRunner.class):引入Spring对JUnit4的支持。
  • @SpringBootTest(classes = HelloWorldApplication.class): SpringBoot Since:1.4.0 版本开始引入,用于指定Spring Boot的启动类。
配置详解

在快速入门实例中,我们轻松地实现了一个简单的 RESTful API 应用,体验了 Spring Boot 的诸多优点。我们用非常少的代码就成功实现了一个 Web 应用, 这是传统 Spring 应用无法办到的。虽然在实现 Controller 时用到的代码是一样的,但是在配置方面,相信大家也注意到了,在上面的例子中,除了 Maven 的配置之外,没有引入任何其他配置。

这就是之前我们提到的, Spring Boot 针对常用的开发场景提供了一系列自动化配置来减少原本复杂而又几乎很少改动的模板化配置内容。但是,我们还是需要了解如何在 Spring Boot 中修改这些自动化的配置内容,以应对一些特殊的场景需求,比如,我们在同一台主机上需要启动多个基千 Spring Boot 的 Web 应用,若不为每个应用指定特别的端口号,那么默认的8080 端口必将导致冲突。

配置文件

上面我们介绍Spring Boot 的工程结构时,提到过 src/rnain/resources 目录是Spring Boot的配置目录,所以当要为应用创建个性化配置时,应在该目录下进行。

Spring Boot 的默认配置文件位置为src/main/resources/application.properties。关于 Spring Boot 应用的配置内容都可以集中在该文件中,根据我们引入的不 同 Starter 模块,可以在这里定义容器端口号、数据库连接信息、日志级别等各种配置信息。比如,我们需要自定义Web模块的服务端口号,可以在 application.properties 中添加 server.port=8888 来指定服务端口为 8888,也可以通过spring.application.name =hello 来指定应用名(该名字在后续SpringCloud中会被注册为服务名)。

Spring Boot 的配置文件除了可以使用传统的 properties 文件之外,还支持现在被广泛推荐使用的YAML文件。

YAML 采用的配置格式不像 properties 的配置那样以单纯的键值对形式来表示,而是以类似大纲的缩进形式来表示。下面是一段 YAML 配置信息:

server:
	pore: 8080

与其等价的 properties 配置如下所示:

server.port=8080

通过 YAML 的配置方式我们可以看到,配置信息利用阶梯化缩进的方式,其结构更为清晰易读,同时配置内容的字符量也得到显著减少。除此之外,YAML还可以在一个单个文件中通过使用 spring.profiles 属性来定义多个不同的环境配置。例如下面的内容,在指定为 test 环境时,server.port 将使用8882端口;而在prod环境中,server.port 将使用8883端口;如果没有指定环境,server.port 将使用8881端口。

server:
	port: 8881
---
spring:
	profiles: test
server:
	port: 8882
---
spring:
	profiles: prod
server:
	port: 8883
自定义参数

除了可以在 Spring Boot 的配置文件中设置各个 Starter 模块中预定义的配置属性, 也可以在配置文件中定义一些我们需要的自定义属性。 比如在 application.properties 中添加:

book.name=SpringBootInit
book.author=Jacob

然后, 在应用中可以通过@Value 注解来加载这些自定义的参数, 比如:

@Component
public class Book {
    @Value("${book.name}")
    private String name;
    @Value("${book.author}")
    private String author;
	//省略getter和setter
}

@Value 注解加载属性值的时候可以支持两种表达式来进行配置, 如下所示。

  • 一种是上面介绍的 PlaceHolder 方式, 格式为$,大括号内为 PlaceHolder。
  • 另 一种是使用 SpEL 表达式 (Spring Expression Language), 格式为#,大括号内为 SpEL 表达式。
参数引用

在 application.properties 中的各个参数之间可以直接通过使用 PlaceHolder 的方式来进行引用,就像下面的设置:

book.name=SpringBootInit
book.author=Jacob
book.desc=${book.author} is writing ${book.name}

book.desc 参数引用了上文中定义的 book.name 和 book.author 属性,最后该属性的值就是 Jacob is writing SpringBootInit。

使用随机数

在一些特殊情况下,我们希望有些参数每次被加载的时候不是一个固定的值,比如密钥、服务端口等。在 Spring Boot 的属性配置文件中,可以通过使用 $ 配置来产生随机的 int值、long值或者 string字符串,这样我们就可以容易地通过配置随机生成属性,而不是在程序中通过编码来实现这些逻辑。

${random}的配置方式主要有以下几种
#随机字符串
com.didispace.blog.value=${random.value}
#随机int
com.didispace.blog.number=${random.int}
#随机long
com.didispace.blog.bignumber=${random.long}
# 10以内的随机数
com.didispace.blog.tes七1=${random.int(l0)}
# 10-20的随机数
com.didispace.blog.test2=${random.int[l0,20]}

该配置方式可以设置应用端口等场景,以避免在本地调试时出现端口冲突的麻烦。

命令行参数

在用命令行方式启动 Spring Boot 应用时,连续的两个减号 -- 就是对 application.properties 中的属性值进行赋值 的标识。所以,java -jar xxx.jar --server.port=8888 命令,等价于在 application.properties 中添加属性server.port= 8888。

通过命令行来修改属性值是 Spring Boot 非常重要的一个特性。通过此特性,理论上已经使得应用的属性在启动前是可变的,所以其中的端口号也好、数据库连接也好,都是可以在应用启动时发生改变的,而不同于以往的 Spring 应用通过 Maven 的 Profile 在编译器中进行不同环境的构建。Spring Boot 的这种方式,可以让应用程序的打包内容贯穿开发、测试以及线上部署,而 Maven 不同Profile的方案为每个环境所构建的包,其内容本质上是不同的。但是,如果每个参数都需要通过命令行来指定,这显然也不是一个好的方案,想要解决这个问题可以使用多环境配置。

多环境配置

我们在开发应用的时候,通常同一套程序会被应用和安装到几个不同的环境中,比如开发、测试、生产等。其中每个环境的数据库地址、服务器端口等配置都不同,如果在为不同环境打包时都要频繁修改配置文件的话,那必将是个非常烦琐且容易发生错误的事。

对于多环境的配置,各种项目构建工具或是框架的基本思路是一致的,通过配置多份不同环境的配置文件,再通过打包命令指定需要打包的内容之后进行区分打包,Spring Boot 也不例外,或者说实现起来更加简单。

在 Spring Boot 中,多环境配置的文件名需要满足 application-.proper巨es的格式,其中对应你的环境标识,如下所示。

  • application-dev.properties: 开发环境。
  • application-test.properties: 测试环境。
  • application-prod.properties: 生产环境。

至于具体哪个配置文件会被加载,需要在 application.properties 文件中通过 spring.profiles.active 属性来设置,其值对应配置文件中的值。如 spring.profiles.active=test 就会加载 application-test.properties配置文件内容。

下面,以不同环境配置不同的服务端口为例, 进行样例实验。

  • 针对各环境新建不同的配置文件 application-dev.properties、application-test.properties、application-prod.properties。
  • 在这三个文件中均设置不同的 server.port 属性,例如,dev 环境设置为1111,test环境设置为2222, prod环境设置为3333。
  • • application.properties中设置 spring.profiles.active=dev, 意为默认以 dev 环境设置。
    测试不同配置的加载。
  • 执行java -jar xxx.jar, 可以观察到服务端口被设置为1111 ,也就是默认的开发环境(dev)。
  • 执行java -jar xxx.jar --spring.profiles.active=test,可以观察到服务端口被设置为2222, 也就是测试环境的配置(test)。
  • 执行java -jar xxx.jar --spring.profiles.active=prod,可以观察到服务端口被设置为3333,也就是生产环境的配置(prod)。

按照上面的实验,可以如下总结多环境的配置思路:

  • 在application.properties中配置通用内容,并设置spring.profiles.active=dev, 以开发环境为默认配置。
  • 在 application-.properties中配置各个环境不同的内容。
  • 通过命令行方式去激活不同环境的配置。
加载顺序

在上面的例子中,我们将 Spring Boot 应用需要的配置内容都放在了项目工程中,已经能够通过 spring.profiles.active 或是通过Maven来实现多环境的支待。但是,当团队逐渐壮大,分工越来越细致之后,往往不需要让开发人员知道测试或是生产环境的细节,而是希望由每个环境各自的负责人(QA或是运维)来集中维护这些信息。那么如果还是以这样的方式存储配置内容,对于不同环境配置的修改就不得不去获取工程 内容来修
改这些配置内容,当应用非常多的时候就变得非常不方便。同时,配置内容对开发人员都可见,这本身也是一种安全隐患。对此,出现了很多将配置内容外部化的框架和工具,后续将要介绍的Spring Cloud Config 就是其中之一,为了后续能更好地理解 Spring Cloud Config 的加载机制,我们需要对 Spring Boot 对数据文件的加载机制有一定的了解。

为了能够更合理地重写各属性的值,Spring Boot 使用了下面这种较为特别的属性加载
顺序:

  1. 在命令行中传入的参数。
  2. SPRING APPLICATION JSON中的属性。 SPRING_APPLICATION_JSON 是以 JSON 格式配置在系统环境变量中的内容。
  3. java:comp/env 中的 JNDI 属性。
  4. Java的系统属性,可以通过 System.getProperties() 获得的内容。
  5. 操作系统的环境变量 。
  6. 通过random.*配置的随机属性。
  7. 位于当前应用 jar 包之外, 针对不同 环境的配置文件内容, 例如 application-.properties 或是YAML定义的配置文件。
  8. 位于当前应用 jar 包之内 , 针对不同 环境的配置文件内容,例如 application-.properties 或是YAML定义的配置文件。
  9. 位于当前应用 jar包之外的 application.properties 和 YAML 配置内容。
  10. 位于当前应用 jar 包之内的 application.properties 和 YAML 配置内容。
  11. 在 @Configuration 注解修改的类中,通过 @PropertySource 注解定义的属性。
  12. 应用默认属性,使用 SpringApplication.setDefaultProperties 定义的内容。

优先级按上面的顺序由高到低,数字越小优先级越高。可以看到,其中第7项和第9项都是从应用jar包之外读取配置文件,所以,实现外部化配置的原理就是从此切入,为其指定外部配置文件的加载位置来取代jar包之内的配置内容。通过这样的实现,我们的工程在配置中就变得非常干净,只需在本地放置开发需要的配置即可,而不用关心其他环境的配置。

监控与管理

在微服务架构中,我们将原本庞大的单体系统拆分成多个提供不同服务的应用。虽然各个应用的内部逻辑因分解而得以简化,但是由于部署应用的数量成倍增长,使得系统的维护复杂度大大提升。对于运维人员来说,随着应用的不断增多,系统集群中出现故障的频率也变得越来越高,虽然在高可用机制的保护下,个别故障不会影响系统的对外服务,但是这些频繁出现的故障需要被及时发现和处理才能长期保证系统处千健康可用状态。为了能对这些成倍增长的应用做到高效运维,传统的运维方式显然是不合适的,所以我们需要实现一套自动化的监控运维机制,而这套机制的运行基础就是不间断地收集各个微服务应用的各项指标情况,并根据这些基础指标信息来制定监控和预警规则,更进一步甚至做到一些自动化的运维操作等。

为了让运维系统能够获取各个微服务应用的相关指标以及实现一些常规操作控制,我们需要开发一套专门用于植入各个微服务应用的接口供监控系统采集信息。而这些接口往往有很大一部分指标都是类似的,比如环境变量、垃圾收集信息、内存信息、线程池信息等。既然这些信息那么通用,难道就没有一个标准化的实现框架吗?

当我们决定用 Spring Boot 来作为微服务框架时,除了它强大的快速开发功能之外,还因为它在 Starter POMs 中提供了一个特殊依赖模块 spring-boot-starter-actuator。引入该模块能够自动为 Spring Boot 构建的应用提供一系列用千监控的端点。

spring-boot-starter-actuator 模块的实现对千实施微服务的中小团队来说,可以有效地省去或大大减少监控系统在采集应用指标时的开发量。当然,它也并不是万能的,有时候也需要对其做一些简单的扩展来帮助我们实现自身系统个性化的监控需求。所以,在本节将详细介绍一些关于 spring-boo七-starter-actuator 模块的内容,包括原生提供的端点以及一些常用的扩展和配置方式等。

初识actuator

在现有的 Spring Boot 应用中引入该模块非常简单,只需要在 pom.xml 的dependency 节点中,新增 spring-boot-starter-actuator 的依赖即可,具体如下:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

重启查看日志:

image-20200814161912835

访问127.0.0.1:8081/actuator

{"_links":
 	{
    "self":{"href":"http://localhost:8081/actuator","templated":false},
    "beans":{"href":"http://localhost:8081/actuator/beans","templated":false},
    "caches-cache":{"href":"http://localhost:8081/actuator/caches/{cache}","templated":true},
        "caches":{"href":"http://localhost:8081/actuator/caches","templated":false},
        "health":{"href":"http://localhost:8081/actuator/health","templated":false},
        "health-path":{"href":"http://localhost:8081/actuator/health/{*path}","templated":true},
        "info":{"href":"http://localhost:8081/actuator/info","templated":false},
        "conditions":{"href":"http://localhost:8081/actuator/conditions","templated":false},
        "configprops":{"href":"http://localhost:8081/actuator/configprops","templated":false},
        "env":{"href":"http://localhost:8081/actuator/env","templated":false},
        "env-toMatch":{"href":"http://localhost:8081/actuator/env/{toMatch}","templated":true},
        "loggers-name":{"href":"http://localhost:8081/actuator/loggers/{name}","templated":true},
        "loggers":{"href":"http://localhost:8081/actuator/loggers","templated":false},
        "heapdump":{"href":"http://localhost:8081/actuator/heapdump","templated":false},
        "threaddump":{"href":"http://localhost:8081/actuator/threaddump","templated":false},
        "metrics-requiredMetricName":{"href":"http://localhost:8081/actuator/metrics/{requiredMetricName}","templated":true},
        "metrics":{"href":"http://localhost:8081/actuator/metrics","templated":false},
        "scheduledtasks":{"href":"http://localhost:8081/actuator/scheduledtasks","templated":false},
        "mappings":{"href":"http://localhost:8081/actuator/mappings","templated":false}}}

上图显示了一批端点定义,这些端点并非我们自己在程序中创建的,而是由spring-boot-starter-actuator 模块根据应用依赖和配置自动创建出来的监控和管理端点。通过这些端点,我们可以实 时获取应用的各项监控指标,比如访间 127.0.0.1:8081/actuator/health 端点。我们可以获得如下信息:

{"status":"UP"}
原生端点

根据端点的作用,可以将原生端点分为以下三大类。

  • 应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与SpringBoot应用密切相关的配置类信息。
  • 度最指标类:获取应用程序运行过程中用于监控的度量指标,比如内存信息、线程池信息、HTTP请求统计等。
  • 操作控制类:提供了对应用的关闭等操作类功能。
应用配置类

由于 Spring Boot 为了改善传统 Spring 应用繁杂的配置内容,采用了包扫描和自动化配置的机制来加载原本集中于 XML 文件中的各项内容。虽然这样的做法让我们的代码变得非常简洁,但是整个应用的实例创建和依赖关系等信息都被离散到了各个配置类的注解上,这使我们分析整个应用中资源和实例的各种关系变得非常困难。而这类端点可以帮助我们轻松获取一系列关于 Spring 应用配置内容的详细报告,比如自动化配置的报告、Bean 创建的报告、环境属性的报告等。

  • /conditions: 原端点名 /autoconfig 2.0 后重命名 /conditions,该端点用来获取应用的自动化配置报告,其中包括所有自动化配置的候选项。同时还列出了每个候选项是否满足自动化配置的各个先决条件。所以,该端点可以帮助我们方便地找到一些自动化配置为什么没有生效的具体原因。该报告内容将自动化配置内容分为以下两部分。

    • positiveMatches 中返回的是条件匹配成功的自动化配置。
    • negativeMatches 中返回的是条件匹配不成功的自动化配置。
  • /beans: 该端点用来获取应用上下文中创建的所有 Bean。

    • bean: Bean 的名称。
    • scope: Bean 的作用域。
    • type: Bean 的 Java 类型。
    • resource: class文件的具体路径。
    • dependencies:依赖的 Bean 名称。
  • /configprops:该端点用来获取应用中配置的属性信息报告。从下面该端点返回示例的片段中,我们看到返回了关于该短信的配置信息, prefix 属性代表了属性的配置前缀,properties 代表了各个属性的名称和值。所以,我们可以通过该报告来看到各个属性的配置路径,比如我们要关闭该端点,就可以通过使用endpoints.configprops.enabled=false 来完成设置。

  • /env: 该端点与 /configprops 不同它用来获取应用所有可用的环境属性报告。 包括环境变量、NM属性、应用的配置属性、命令行中的参数。从下面该端点返回的示例片段中,可以看到它不仅返回了应用的配置属性,还返回了系统属性、环境变量等丰富的配置信息,其中还包括了应用还没有使用的配置,所以它可以帮助我们方便地看到当前应用可以加载的配置信息,并配合@ConfigurationProperties 注解将它们引入到我们的应用程序中来进行使用。另外, 为了配置属性的安全,对于一些类似密码等敏感信息,该端点都会进行隐私保护, 但是我们需要让属性名中包含 password、secret、key这些关键词, 这样该端点在返回它们的时候会使用*来替代实际的属性值。

  • /mappings:该端点用来返回所有 Spring MVC 的控制器映射关系报告。

  • /info:该端点用来返回一些应用自定义的信息。默认清况下,该瑞点只会返回一个空的 JSON 内容。我们可以在 apptication.properties 配置文件中通过 info 前缀来设置一些属性,比如下面这样:

info.app.name=hello_world
info.app.version=v1

再访问 /info 端点我们可以得到下面的返回报告,其中就包含了上面我们在应用中自定义的两个参数。

{
    "app":{
        "name":"hello_world",
        "version":"v1"
    }
}
度量指标类

上面我们所介绍的应用配置类端点所提供的信息报告在应用启动的时候就已经基本确定了其返回内容, 可以说是一个静态报告。而度量指标类端点提供的报告内容则是动态变化的,这些端点提供了应用程序在运行过程中的一些快照信息,比如内存使用情况、HTTP 请求统计、外部资源指标等。这些端点对于我们构建微服务架构中的监控系统非常有帮助,由于 Spring Boot 应用自身实现了这些端点,所以我们可以很方便地利用它们来收集我们想要的信息,以制定出各种自动化策略。下面,我们就来分别看看这些强大的端点功能。

  • /metrics:该端点用来返回当前应用的各类重要度量指标,比如内存信息、线程信息、垃圾回收信息等。

  • /health:该端点在一开始的示例中我们已经使用过了,它用来获取应用的各类健康指标信息。在 spring-boot-starter-actuator 模块中自带实现了一些常用资源的健康指标检测器。这些检测器都通过 Healthindicator 接口实现,并且会根据依赖关系的引入实现自动化装配。

  • /dump:该端点用来暴露程序运行中的线程信息。它使用java.lang.rnanagernent.ThreadMXBean 的 durnpAllThreads 方法来返回所有含有同步信息的活动线程详情。

  • /trace:该端点用来返回基本的 HTTP 跟踪信息。默认情况下,跟踪信息的存储采用org.springfrarnework.boot.actuate.trace.InMernoryTraceRepository 实现的内存方式,始终保留最近的100条请求记录。

操作控制类

之前介绍的所有端点都是用来反映应用自身的属性或是运行中的状态,相对于操作控制类端点没有那么敏感,所以它们都是默认启用的。而操作控制类端点拥有更强大的控制能力,如果要使用它们的话,需要通过属性来配置开启操作。

在原生端点中,只提供了一个用来关闭应用的端点:/shutdown。可以通过如下配置开启它:endpoints.shutdown.enabled=true 在配置了上述属性之后,只需要访问该应用的/shutdown端点就能实现关闭该应用的远程操作。由于开放关闭应用的操作本身是一件非常危险的事,所以真正在线上使用的时候,需要对其加入一定的保护机制,比如定制actuator的端点路径、整合SpringSecurity进行安全校验等。