• 第03篇_SpringBoot基础应用

    第01章_SpringBoot概述

    第一节 SpringBoot简介

    1. 什么是SpringBoot?

    SpringBoot 是 Spring 项目的一个子工程,它将一些主流的技术与 Spring 框架进行了整合,基于约定优于配置的思想,为开发者提供了一个方便快捷的工程脚手架

     

    2. SpringBoot的主要作用

    注意:

    1. 由于SpringBoot需要基于模块装配+条件装配+SPI机制等实现“约定大于配置”的思想,因此一般采用注解配置的方式。

    2. 基于 XML 的配置方式编写更灵活、易修改(无需重新打包),但是不方便整合场景制作启动器(需要根据不同的情况进行注册)。

     

     

    第二节 入门案例

    SpringBoot为我们提供了非常快速的开发体验,通过下面几个步骤,将会搭建一个简单的Web应用程序。

     

    1. 继承SpringBoot父工程

    新建一个Maven项目,在pom.xml文件中继承SpringBoot父工程:spring-boot-starter-parent

    注意

    1. 根据项目情况选择合适的SpringBoot版本,并在文档的 system-requirements 章节查看 Maven 和 JDK 的最低版本要求。

     

    2. 引入场景启动器

    我们开发的是一个Web应用,则在pom.xml文件中引入 Web 应用场景的启动器:spring-boot-starter-web

     

    3. 编写启动类

    SpringBoot应用一般需要一个启动类来引导程序的启动开启自动配置

     

    4. 编写业务类

    编写一个简单的/hello接口,来测试下我们的SpringBoot应用。

     

    4. 运行和测试

    直接在IDEA中执行main函数,或者在工程根目录(pom.xml文件所在目录)通过mvn spring-boot:run命令启动。

    img

    当启动完成后,点击http://localhost:8080/hello即可进行访问!

    image-20220801235026608

     

    5. 发布可执行Jar包

    由于Java 没有提供加载嵌套 jar 文件的标准方法,因此,需要引入一个插件spring-boot-maven-plugin来支持它。

    然后,在工程根目录(pom.xml文件所在目录)使用mvn package -Dmaven.test.skip=true命令来对其进行打包。

    image-20220802000022576

    打包完成后,一般会生成SpringBoot-demo-1.1-SNAPSHOT.jar.originalSpringBoot-demo-1.1-SNAPSHOT.jar两个文件。前者为 Maven 生成的原始 Jar 文件,仅包含当前工程代码,一般提供给其它工程引用;后者为 SpringBoot 重新打包后生成的可执行jar文件,额外包含了工程的所有依赖Jar包及启动代码。

    image-20220802000105435

    最后,使用java -jar SpringBoot-demo-1.0-SNAPSHOT.jar命令来启动和测试它!

    image-20220802000242297

     

    6. 远程调试

    如果需要支持远程调试,请使用如下命令启动你的 SpringBoot 应用程序:

     

     

    第三节 相关概念详解

    1. SpringBoot父工程

    一般来说,SpringBoot 项目都会继承spring-boot-starter-parent作为父工程,它提供了版本管理默认配置

    除此之外,SpringBoot 父工程还会进行一些插件的默认配置以及对配置文件(application.properties)的进行敏感资源过滤等。

     

    父工程中的默认属性,可以通过覆盖的方式修改它们,如下例所示:

     

    如果不想继承父工程,则也可以通过如下方式来使用 SpringBoot 的版本管理功能,但是你不能使用覆盖的方式去修改默认属性。

     

     

    2. 场景启动器

    场景启动器(Starter)是SpringBoot管理复杂依赖关系的一种手段,你可以把它理解为一些用于某项功能所需要依赖的集合。

    SpringBoot官方为一些应用场景内置相应的启动器,一般以spring-boot-starter-开头,下面是常见的启动器列表:

    NameDescriptionPom
    spring-boot-starter核心启动器,包括自动配置日志记录YAML格式支持Pom
    spring-boot-starter-actuator提供生产就绪功能,帮助您监视和管理应用程序Pom
    spring-boot-starter-aop使用SpringAOP和AspectJ进行面向切面编程Pom
    spring-boot-starter-jdbc使用JDBC访问数据库(使用HikariCP连接池)Pom
    spring-boot-starter-test集成了JUnit、Hamcrest、Mockito等一些测试依赖Pom
    spring-boot-starter-web构建基于SpringMVC的Web应用程序(默认嵌入tomcat容器)Pom
    spring-boot-starter-log4j2使用Log4j2进行日志记录Pom
    spring-boot-starter-logging使用Logback进行日志记录(默认的日志启动器)Pom
    spring-boot-starter-tomcat使用Tomcat作为嵌入式servlet容器Pom

    除上述一些官方内置的启动器外,第三方项目也可以基于开放的接口定义自己的启动器,如MyBatis定义的mybatis-spring-boot-starter启动器等。更多第三方启动器,可参考GitHub上spring-boot-starters模块中的README file

     

     

    3. @SpringBootApplication

    @SpringBootApplication注解用于标识该应用为一个SpringBoot应用程序,它由如下三个注解组成:

    注意:

    1. 如果需要注册不在扫描路径内的 Spring 组件,可以使用 Spring 的@Import@ImportResource注解。

     

    如果想禁用某个自动配置,可以使用该注解的exclude属性,如以下示例所示:

    如果该类不在CLASSPATH中,则可以使用相关的excludeName属性,并指定全限定类名。除此之外,您也可以在application.yml中使用spring.autoconfigure.exclude属性来控制要排除的自动配置类的列表。

     

     

     

    第02章_SpringBoot核心

    第一节 SpringApplication

    1. 创建SpringApplication

    SpringApplication类提供了一个静态方法run,可以方便的从main函数来启动Spring应用程序,如下例所示。

    当然,你也可以创建一个本地实例,并对其进行自定义设置后再启动。

    如果你更喜欢流式编程(Fluent Builder API),也可以使用如下方式。

    此外,利用 SpringapplicationBuilder 可以构建具有层次关系的 Spring Boot 应用程序:

     

     

    2. 启动SpringApplication

    1) 如何启动

    入门案例中已经讲解了如何启动SpringBoot应用程序。

     

    2) 生成PID和PORT文件

    META-INF/spring.factories文件中添加如下配置后,就可以生成相应的PIDPORT文件:

    默认的文件名为application.portapplication.port,可以使用spring.pid.file=/var/log/app.pid属性进行修改。

     

    3) 启动失败分析(FailureAnalyzer)

    如果程序启动失败,SpringBoot 会通过已注册的FailureAnalyzer来分析错误,以提供专用的错误消息和解决该问题的具体措施。

    如端口被占用时会打印如下错误报告:

     

    如果需要进行扩展,可继承针对于特定异常类型的AbstractFailureAnalyzer<T extends Throwable>抽象类,并在META-INF/spring.factories中通过如下配置进行注册。

    提示:

    1. 使用JSR-303注解出现异常时也会由FailureAnalyzer来分析错误。

    2. 在FailureAnalyzer中,可以通过实现BeanFactoryAware和EnvironmentAware接口来获取BeanFactory和Environment。

     

     

    3.SpringApplication的常用设置

    SpringApplication可以在创建时通过其JavaAPI或spring.main前缀的外部化属性进行自定义设置。

     

    1) 设置Banner

    SpringBoot应用在启动时会自动加载类路径下的banner.txt文件或同名.gif/.jpg/.png结尾的图片(转化为ASCII艺术作品)来打印Banner。banner.txt文件示例如下:

     

    在banner.txt中,可以使用下面一些占位符:

    占位符描述示例
    ${application.version}MANIFEST.MF文件中声明的应用程序的版本号(Implementation-Version: 1.0)1.0
    ${application.formatted-version}MANIFEST.MF文件中声明的应用程序的版本号(格式化)(v1.0)
    ${spring-boot.version}您正在使用的 Spring Boot 版本2.1.1.RELEASE
    ${spring-boot.formatted-version}您正在使用的 Spring Boot 版本(格式化)(v2.1.1.RELEASE)
    ${Ansi.Xxx}
    ${AnsiColor.Xxx}
    ${AnsiBackground.Xxx}
    ${AnsiStyle.Xxx})
    其中Xxx是 ANSI 转义代码的名称。有关详情,请参见AnsiPropertySourceAnsiColor.GREEN
    AnsiBackground.RED
    AnsiStyle.BOLD
    ${application.title}MANIFEST.MF文件中声明的应用程序标题(Implementation-Title: MyApp)。MyApp

     

    可通过下面一些属性来进行相关配置:

    属性作用
    spring.banner.location指定一个文本文件作为banner
    spring.banner.charset指定banner文件的字符集,默认为UTF-8
    spring.banner.image.location指定一张gif/jpg/png格式的图片作为banner,图片将转化为ASCII艺术作品展示
    spring.main.banner-mode指定banner打印在控制台(console)还是日志(log),或者干脆不打印("off")

     

    除上述属性配置的方式外,也可以通过实现接口的方式来设置Banner。首先实现org.springframework.boot.Banner接口。

    然后在启动应用前通过SpringApplication.setBanner(…)方法进行设置。

    注意:

    1. 该实现类会被注册为名称叫springBootBanner的单例Bean。

     

     

    2) 指定Web环境

    SpringApplication根据当前依赖环境来为你创建合适的ApplicationContext实现。

    如果需要修改,你可以通过setWebApplicationType(WebApplicationType.Xxx)轻松覆盖它!

    WebApplicationType用途
    SERVLET指定为SpringMVC环境
    REACTIVE指定为Spring WebFlux环境
    NONE指定为Junit测试环境

    注意:

    1. 也可以使用spring.main.web-application-type属性来修改WEB环境或直接通过setApplicationContextClass(…)来显式指定ApplicationContext 的实现!

     

    3) 延迟初始化

    如果需要设置Bean在使用时才创建,而不是在应用程序启动期间创建,可以设置其延迟初始化,但这会延迟应用程序问题的发现。

     

     

    4. 生命周期回调

    1) SpringApplicationRunListener

    SpringApplicationRunListener贯穿SpringBoot启动的全程,是最常用的干涉SpringBoot启动过程的扩展点。

     

    2) ApplicationListener

    SpringBoot 内置了 一个 SpringApplicationRunListener 的实现类 EventPublishingRunListener,用于在上下文启动时发布一些关键事件,提供给使用者干涉上下文启动过程:

    如下定义了一个 ApplicationStartingEvent 事件的监听器,可通过注册为Bean的方式来对其进行注册。

    但上述部分事件触发时,可能 ApplicationContext 尚未创建完成,需要在META-INF/spring.factories文件中注册上述创建的监听器:

    或者通过编程方式使用SpringApplication.addListeners(…)方法或SpringApplicationBuilder.listeners(…)方法注册:

    或者在application.properties文件中进行注册:

     

     

    3) ApplicationContextInitializer

    ApplicationContextInitializer在Springboot启动过程(refresh方法前)调用,是一种更加简单的介入方式。

    注册方式和监听器类似,推荐在META-INF/spring.factories文件中进行注册。

    当然,也可以使用SpringApplication.addInitializers(…)方法、SpringApplicationBuilder.initializers(…)方法或context.initializer.classes属性注册它们。

     

     

    4) EnvironmentPostProcessor

    EnvironmentPostProcessor可用于在刷新应用程序上下文之前自定义Environment。如下示例从 Classpath 加载 YAML 配置文件:

    同样的,你需要在META-INF/spring.factories中进行注册,而不能通过注册组件的方式来注册它。

    注意:

    1. 在处理属性加密时,一般也是通过EnvironmentPostProcessor实现的。

     

    5) ApplicationRunner/CommandLineRunner

    如果在SpringApplication启动的最后,需要运行一些特定的代码,可以实现ApplicationRunnerCommandLineRunner接口,两者工作方式一致,仅 run 方法的参数类型不同。

    注意:

    1. 你可以通过实现Ordered接口或使用@Order注解来调整其执行顺序,值越小,优先级越高,越先执行。

     

     

    5. 获取命令行参数

    如果需要访问启动时的命令行参数,可以通过注入org.springframework.boot.ApplicationArguments来获取。

    除此之外,SpringBoot还向容器注册了一个CommandLinePropertySource,这样就可以使用@Value注解直接注入单个应用程序参数。

     

     

    6. 关闭SpringApplication

    每个应用在启动时都会向JVM注册一个关闭钩子,以确保在退出时正常关闭,保证所有标准的 Spring 生命周期回调如期生效。

    另外,如果希望在调用SpringApplication.exit()时返回特定的退出代码,则可以实现ExitCodeGenerator接口,然后可以将此退出代码传递给System.exit(),以将其作为状态代码返回,如以下示例所示:

    此外,ExitCodeGenerator接口可能会通过异常实现。遇到此类异常时,Spring Boot 将返回已实现的 getExitCode() 方法提供的退出代码。

     

     

     

    第二节 外部化属性配置

    SpringBoot支持使用Properties文件YAML文件环境变量命令行参数等多种方式来配置外部属性,并使用Environment进行统一管理,然后通过@Value注解注入到Bean,或通过@ConfigurationProperties注解绑定到结构化对象后使用。

     

    1. 加载顺序

    SpringBoot从不同来源加载的外部属性允许被覆盖,它们之间的优先级如下:

    1. 主目录($HOME)中Devtools配置的全局属性(位于~/.spring-boot-devtools.properties)。

    2. 通过@TestPropertySource等测试相关注解配置的属性。

    3. 命令行参数

    4. SPRING_APPLICATION_JSON中配置的属性。

    5. 来自Web环境的属性:ServletConfig的初始化参数、ServletContext的初始化参数和来自java:comp/env的JNDI属性。

    6. 通过System.getProperties()获取的Java系统属性。

    7. 系统环境变量

    8. 通过RandomValuePropertySource生成随机值的属性(属性值为random.*前缀)。

    9. 特定Profile的配置文件(application-{profile}.properties或类似YAML)(Jar包外部的优先)。

    10. 默认配置文件(application.properties或类似YAML)(Jar包外部的优先)。

    11. @Configuration类上的@PropertySource注解加载的配置文件

    12. 通过SpringApplication.setDefaultProperties指定的默认属性。

     

     

    2. 属性配置

    1) 命令行参数

    SpringBoot会将任何命令行选项参数(以--开头)或JVM属性(以-D开头)添加到Environment中,如下所示:

    小提示:

    1. 可以使用SpringApplication.setAddCommandLineProperties(false)禁用此默认行为。

    2. 可以在属性值中使用占位符来减短属性长度,如属性server.port=${port:8080},只需通过--port=9000配置即可。

     

     

    2) SPRING_APPLICATION_JSON

    SPRING_APPLICATION_JSON是通过命令行参数、系统变量、环境属性等其它方式配置的内联JSON,SpringBoot会对其进行展开,提取JSON配置的属性。使用系统变量的配置方式如下:

    img

    其它配置方式可参考如下示例:

     

    3) 随机值属性

    SpringBoot提供了RandomValuePropertySource类用于支持随机值的配置,类型可以是intlonguuid字符串等,示例如下:

    其中random.intrandom.long属性支持一个范围后缀,其语法为:OPEN value (,max) CLOSE,其中OPEN和CLOSE可以是任何字符,max是整数。如果提供了max,则value是最小值,max是最大值(不含)。

     

    4) 特定Profile的配置文件

    Profiles是一种策略式的组件或配置文件的加载方式,可以方便的切换不同的环境配置,使用时分为标记激活两个步骤。

     

    对于Spring组件可以使用@Profile注解进行标记:

    对于多个配置文件,可通过属性文件名-profile的方式来标记:

    对于YML分段文件,可以使用spring.profiles属性来标记:

     

    可以通过spring.profiles.active属性来指定需激活的profile列表,该属性可以配置在属性文件中:

    也可以在命令行上指定它:

    注意:

    1. 该属性可以被覆盖,这意味着您可以在属性文件中指定默认的active配置,然后使用命令行开关“替换”它们。

     

    有时候,不需要对整个active属性进行替换,而是在此基础上附加一些额外的profile,可以使用spring.profiles.include属性。

    除此之外,也可以使用编程的方式实现:

     

    5) 默认配置文件

    SpringBoot使用application.properties/application.yaml/application.yml(按优先级从高到低排序)作为默认的属性配置文件,将会从下列路径依次加载,后加载的同名属性会将之前的值覆盖。

     

    如果想修改默认属性文件名,可以使用spring.config.name进行指定。

     

    如果想修改默认加载目录,可以使用spring.config.location指定或通过spring.config.additional-location进行附加。

     

    如果想同时指定加载目录和属性文件名,也可以使用spring.config.location属性:

    注意:

    1. 由于上述属性在加载属性文件之前被使用,因此你必须使用系统变量系统属性或命令行参数等高优先级的配置方式。

    2. 大多操作系统不支持使用句点分隔的环境变量名,你可以使用下划线形式代替(例如:SPRING_CONFIG_NAME)。

     

    6) 其它配置文件

    SpringBoot默认从application.properties文件加载属性配置,如果存在其它properties类型的配置文件,可以通过@PropertySource注解来加载。示例如下:

     

    7) YML格式简介

    YAML是JSON的超集,是一种用于指定层次结构配置数据的便捷格式,非常适合用来做以数据为中心的配置文件。spring-boot-starter自动引入了SnakeYAML库用于支持yaml格式,其基本语法如下:

    下面是使用yaml配置不同类型数据的语法格式:

    具体案例可参考属性注入和绑定章节!

     

     

    3. 属性注入和绑定

    1) 通过@Value("${Xxx}")注入

    注意:

    1. 该注解不能在静态变量常量上使用!

     

    2) 绑定到属性Bean

    SpringBoot提供了@ConfigurationProperties注解将属性配置与强类型的JavaBean进行绑定,并且支持宽松的绑定格式、属性值转换、属性值验证及元数据提示等,使用起来更加方便。

    有如下一个YML配置文件,已通过YmlLoadEnvironmentPostProcessor(见第二章节)进行加载:

    我们可以通过如下JavaBean进行属性绑定,绑定后可直接通过容器中的PersonProperty实例使用绑定属性。

    提示:@ConfigurationProperties有一些属性可以控制绑定时的行为。

    • ignoreUnknownFields:默认为true,如果设置为false,则在属性文件中提供了属性类没有的属性时报错。

    • ignoreInvalidFields:默认为false,如果设置为true,则在属性绑定失败时不报错。

     

    如果该Bean不是Spring组件,则在必须在其它Spring组件上使用@EnableConfigurationProperties(Person.class)注解将其拉起。

     

    属性Bean以属性前缀-全类名作为Bean名称,如果未配置属性前缀,则Bean名称为全类名。可以像使用其他任何Bean一样注入该属性Bean并使用,如构造函数注入、@Bean方法注入、@Autowird注入等。

    注意:

    1. 必须为配置的属性提供相关的getter/setter方法及默认构造函数,但二级属性等除外。

    2. 不支持对静态属性进行绑定。

    3. 使用@ConfigurationProperties还可让您生成元数据文件,IDE可以使用这些元数据文件为提供配置提示。

     

    3) 注入到第三方组件

    如果需要将属性绑定到不可修改的第三方组件等,可以在@Bean方法上加@ConfigurationProperties注解来实现:

     

    4) 宽松的绑定规则

    SpringBoot使用一些宽松的规则将加载的属性绑定到属性Bean,因此属性名称和Bean中的属性名不需要完全匹配。如下示例:

    可以使用下列一些方式来配置firstName的属性值:

    注意:

    1. 前提:@ConfigurationProperties注解中的prefix属性必须是小写且由-分隔的形式,如acme.my-project.person

    2. 属性名建议使用小写的 kebab 格式存储,例如my.property-name=acme

    3. 如需在环境变量中配置列表数据,可以使用带下划线的数字值表示,如MY_ACME_1_OTHER = my.acme[1].other

    4. 绑定到Map属性时,如果key包含小写字母、数字字符或-以外的任何内容,则必须使用[]括起来,否则将会被删除。

     

     

    4. 属性覆盖与合并

    默认情况下,SpringBoot会直接覆盖旧的属性值,但对于复杂类型,做了一些特殊处理。

     

    1) List类型属性

    如果在多个属性源配置了同名的List属性,处理方式和基本属性一致,采用完全覆盖的方式,取优先级最高的配置。如下属性:

    在外部属性源存在多个list的配置如下:

    最终生效情况如下:

     

    2) Map类型属性

    如果在多个属性源配置了同名的Map属性,采用合并的方式进行处理。如下属性:

    在外部属性源存在多个map的配置如下:

    最终生效情况如下:

     

     

    5. 属性转换

    在SpringBoot绑定属性时,会尝试将外部属性值强制转换为对应的类型,几种特殊类型及如何自定义类型转换如下。

     

    1) Duration类型

    Duration类型专门用于表达持续时间,SpingBoot在属性绑定时对其做了特殊处理。支持下面一些格式:

    1. 常规long表示形式(使用毫秒作为默认单位,除非已指定@DurationUnit)。

    2. 由 java.util.Duration使用的标准 ISO-8601 格式。

    3. 值和单位相结合的更易读的格式(例如10s表示10秒),常见的单位还有:ns、us、ms、s、m、h、d等。

     

    2) DataSize类型

    DataSize类型专门用于表达数据大小,SpingBoot在属性绑定时对其做了特殊处理。支持下面一些格式:

    1. 常规的long表示形式(除非已指定@DataSizeUnit,否则使用字节作为默认单位)。

    2. 值和单位耦合在一起的更具可读性的格式(例如10MB表示10兆字节),常见的单位还有:B、KB、MB、GB、TB等。

     

    3) 自定义类型转换

    如果需要自定义类型转换,可以使用属性编辑器(CustomEditorConfigurer)、Converters(@ConfigurationPropertiesBinding)或ConversionService(名称为conversionService的Bean)等,请参考 Spring 相关章节。

    注意:

    1. 该类型Bean在生命周期中非常早的初始化,请注意所使用的依赖。

     

     

    6. 属性值验证

    在绑定属性时,如果Classpath上有兼容的JSR-303 实现,那么还支持JSR-303标准定义的@Validated注解进行属性值的验证。

    除此之外,也可以通过在创建属性Bean的@Bean方法上使用@Validated注解来触发验证。

    注意:

    1. 尽管嵌套属性在绑定时也会验证,但是最好将关联的字段注解为@Valid。这样可以确保即使没有嵌套属性也可以触发验证。

     

    如果需要对Validator进行扩展,可以创建名为configurationPropertiesValidator的bean来添加自定义Spring Validator,但注意,其@Bean方法应声明为static(防止配置属性验证器过早实例化)。

     

     

     

    第三节 使用自动配置

    对于一些开源或商业项目,或者是其它的一些共享Jar包,可能也希望使用SpringBoot提供的自动配置功能,下面将会介绍如何使用。

     

    1. AutoConfiguration类

    AutoConfiguration类是SpringBoot中用于实现自动配置的特殊配置类,其通过一系列的条件注解约束配置在特定的条件下才会生效。

    如需使 SpringBoot 识别自定义的自动配置类,则必须在类路径下的META-INF/spring.factories文件中进行配置。

    如果需要指定自动配置类的加载顺序,可以通过@AutoConfigureOrder注解来声明,它和 Spring 的 Order 注解类似。除此之外,也可以通过@AutoConfigureAfter@AutoConfigureBefore注解来配置指定Bean之间的先后顺序。

    注意:

    1. 自动配置类一般在@Configuration上加proxyBeanMethods=false属性,表示禁止代理@Bean方法,这样在代码中显式调用@Bean方法时不会返回容器中已存在的值。

     

     

    2. @Conditional注解

    条件注解@Conditional是实现自动配置的关键,SpringBoot支持许多类型的条件注解。

     

    1) 类条件

    @ConditionalOnClass@ConditionalOnMissingClass使自动配置仅在特定类存在/缺失时生效,可以使用value属性直接引用特定的类,或使用name属性指定其字符串形式的全类名。

    注意:

    1. 由于注解的元数据是通过ASM进行解析的,因此即使引用的类不在类路径上,也可以使用value属性进行引用。

    2. 但上述注解形成的组合注解,无法使用value属性引用类路径下不存在的类。

     

    3) Bean条件

    @ConditionalOnBean@ConditionalOnMissingBean使自动配置仅在特定的Bean存在/缺失时生效,可以使用value属性指定Bean的类型,如果该注解加在@Bean方法上,则默认值为方法的返回值类型。此外,也可以使用name属性指定Bean的名称。

    除此之外,还可以使用search属性限制搜索Bean时应考虑的ApplicationContext层次结构。

    注意:

    1. 该条件注解是根据当前已处理的内容来评估的,因此需要特定注意Bean的初始化顺序。

     

    3) 属性条件

    @ConditionalOnProperty使自动配置仅在Spring环境中包含特定的属性时生效,分别使用prefixname属性来指定应检查的属性,默认情况下,当检测的属性存在且不等于 false 时生效。

    可以使用havingValue属性来设置与之对比的值,当属性存在且值相同时则加载。此外,matchIfMissing属性可以设置指定的属性不存在时是否进行加载。

     

    4) 资源条件

    @ConditionalOnResource使自动配置仅在特定资源存在时才生效,使用通常的Spring约定来指定资源,如:file:/home/user/test.dat。

     

    5) Web环境

    @ConditionalOnWebApplication@ConditionalOnNotWebApplication使自动配置仅在Web环境下生效。Web环境指使用了WebApplicationContext,或定义了session范围,或具有StandardServletEnvironment的环境。

     

    6) SpEL条件

    @ConditionalOnExpression注解允许基于SpEL expression的结果决定配置是否生效。

     

    7) byType条件

    @ConditionalOnSingleCandidate注解使自动配置仅在当容器中具有唯一的该类型Bean(或存在主候选对象)时生效。

     

    8) 自定义条件

     

     

    3. 自定义启动器

    启动器是为某个使用场景提供的一系列依赖和自动配置的集合。通常来说,可以将启动器分为两个部分:

    实际开发中,也可以将autoconfigure模块直接合并到starter模块之中。

    注意:

    1. 启动器必须直接或间接的引用核心Spring Boot启动程序spring-boot-starter

    如果启动器需要暴露自定义属性,可以通过下面注解处理器来生成元数据文件(META-INF/spring-configuration-metadata.json),以便IDE进行配置提示。

     

     

     

    第03章_SpringBoot整合

    第一节 整合Web服务器

    每个SpringBoot Web应用程序都会包含一个嵌入式Web服务器,下面介绍如何进行替换和配置。

     

    1. 基本使用

    1) 选择嵌入式Web服务器

    基于 Servlet 的 Web 应用程序(spring-boot-starter-web),默认的嵌入式服务器为Tomcat,可以将它替换为JettyUndertow等:

    基于 Reactive 的 Web 应用程序(spring-boot-starter-webflux),默认的嵌入式服务器启动器为spring-boot-starter-reactor-netty,可以通过spring-boot-starter-tomcatspring-boot-starter-jettyspring-boot-starter-undertow来进行替换。

    注意:

    1. 可以通过spring.main.web-application-type=none属性来禁止启动类路径下的嵌入式服务器。

     

    2) 配置和获取HTTP端口

    可以使用server.port属性来设置Web服务器的HTTP端口,默认的端口号为8080

     

    如需在应用运行时获取HTTP端口,可以监听WebServerInitializedEvent事件(Web服务器启动完成时触发)。

     

    如需获取测试时@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)生成的随机端口,可以通过@LocalServerPort注解注入,或通过local.server.port属性获取。

     

    3) 配置访问日志

     

    4) 其它配置

    如果需要修改其它相关配置,可以在application.properties文件中修改,常用的配置如下:

    配置属性说明
    server.portHTTP 请求的端口
    server.servlet.session.persistence会话是否持久
    server.servlet.session.timeout会话超时时间
    server.servlet.session.store-dir会话数据的位置
    server.servlet.session.cookie.*会话 cookie 配置
    server.error.path错误页面的位置

    注意:

    1. 关于Servlet容器的更多配置请参考ServerProperties类,其中还包含一些如server.tomcat.*前缀等特定于容器的配置。

    2. 如果在CentOS上使用Tomcat,生成的临时文件可能被自动清理,可使用server.tomcat.basedir属性配置到其它位置。

     

     

    2. HTTP特性支持

    1) HTTP响应压缩

    嵌入式Tomcat、Jetty和Undertow服务器都支持HTTP响应压缩,可通过如下属性来开启和配置。

     

    2) 配置HTTPS

    HTTPS是以安全为目标的HTTP通道,在HTTP的基础上通过传输加密身份认证保证了传输过程的安全性。

    在SpringBoot应用程序中可以通过server.ssl.*前缀的相关属性来配置SSL以支持HTTPS。

    注意

    1. 更多属性配置可参考源代码:org.springframework.boot.web.server.Ssl.java。

     

    如果需要同时支持HTTP和HTTPS,可参考spring-boot-sample-tomcat-multi-connectors案例给Tomcat配置额外的HTTP连接器。

    当然,也可以直接通过编程方式添加HTTPS连接器来同时支持HTTP和HTTPS,如下所示:

     

    3) 支持HTTP/2

    HTTP/2也被称为HTTP 2.0,相对于HTTP 1.1新增多路复用压缩HTTP头划分请求优先级服务端推送等特性,解决了在HTTP 1.1中一直存在的问题,优化了请求性能,同时兼容了HTTP 1.1的语义。

    SpringBoot应用程序可以通过如下属性来开启HTTP/2支持。

    注意

    1. Spring Boot不支持h2c,即HTTP/2 协议的明文版本。因此您必须首先配置SSL。

    2. 基本环境要求:

      • Undertow1.4.0+:只需要JDK8+环境。

      • Jetty9.4.8+:还需要附加依赖项org.eclipse.jetty:jetty-alpn-conscrypt-server和org.eclipse.jetty.http2:http2-server。

      • Tomcat 9.0.x:最好为JDK9+,也可以使用JDK8,则需要添加libtcnative库及其依赖项(-Djava.library.path=/usr/local/opt/tomcat-native/lib)。

     

     

    3. Web服务器高级配置

    1) WebServerFactoryCustomizer

    如果提供的属性配置无法满足你对Web服务器的配置需要,还可以通过实现WebServerFactoryCustomizer接口来自定义Web服务器。

     

    2) WebServerFactory

    作为最终的手段,你还可以定义自己的WebServerFactory组件,来覆盖掉Spring Boot提供的对应组件,但是在这种情况下,您不能再依赖server名称空间中的配置属性。

    注意:

    1. 如果您需要做一些更奇特的操作,还提供了几种受保护的方法“钩子”。有关详情,请参见源代码文档。

     

     

    第二节 整合日志框架

    1. 日志的基本使用

    1) 默认日志实现

    SpringBoot中默认使用JCL(Java Common Logging)门面记录所有内部日志,并为LogbackLog4J2JUL提供了默认配置:

    日志实现默认配置文件(通过logging.config属性可修改)
    Logbacklogback.xml、logback-spring.xml、logback.groovy、logback-spring.groovy
    Log4j2log4j2.xml、log4j2-spring.xml
    JULlogging.properties

    注意:

    1. 在使用spring-boot-starter-web启动器时,默认采用Logback日志实现,默认级别为INFO

    2. 推荐使用以-spring结尾的日志配置文件,以便 Spring 控制日志框架的初始化。

    3. 不推荐在以 java -jar 方式运行时使用JUL日志实现,可能会引发类加载错误。

     

    2) 设置日志级别

    SpringBoot默认将日志输出到控制台,并打印ERRORWARNINFO级别的日志,可通过如下配置修改:

    注意:

    1. 日志级别可通过debug=truetrace=true等属性或命令行方式java -jar my-app.jar --trace进行全局修改。

    2. Logback框架没有FATAL级别,它将会被映射到ERROR。

     

    3) 其它日志配置属性

    下面是一些可用的日志配置属性,以及通过系统属性配置时的属性名:

    Spring EnvironmentSystem PropertyComments
    logging.exception-conversion-wordLOG_EXCEPTION_CONVERSION_WORD记录异常时使用的转换字
    logging.fileLOG_FILE日志文化目录和文件名
    logging.file.max-sizeLOG_FILE_MAX_SIZE最大日志文件大小(默认为10M,后缀可以为KB、MB和GB)
    logging.file.max-historyLOG_FILE_MAX_HISTORY要保留的最大归档日志文件数(默认无限制)
    logging.pathLOG_PATH日志文件目录,默认文件名为spring.log
    logging.pattern.consoleCONSOLE_LOG_PATTERN在控制台上使用的日志模式(stdout)
    logging.pattern.dateformatLOG_DATEFORMAT_PATTERN记录日期格式的附加模式
    logging.pattern.fileFILE_LOG_PATTERN文件中使用的日志模式
    logging.pattern.levelLOG_LEVEL_PATTERN渲染日志级别时使用的格式(默认为%5p)
    PIDPID当前进程ID

    注意:

    1. 日志功能在创建容器之前进行初始化,因此必须通过系统属性或更高级别的属性配置方式来修改日志属性。

     

     

    2. 使用SLF4J->Logback

    使用Web启动器时,会自动引入SLF4J和Logback的相关依赖,可通过logback.xmllogback-spring.xml对其进行配置。

     

    1) logback.xml配置

    SpringBoot在org/springframework/boot/logging目录下提供一份base.xml文件,对LogBack进行了一些默认配置:

    可以在应用的LogBack配置文件中通过如下方式引入来使用:

    当然,也可以从零开始定义自己的配置:

     

    2) logback-spring.xml配置

    如果通过logback-spring.xmllogging.config属性指定的其它文件来配置logback,则可以使用一些SpringBoot提供的扩展功能。

    通过<springProfile>标签可以方便的将配置切换到不同环境。

    通过<springProperty>标签可以在logback-spring.xml文件中访问Spring环境属性。

    注意:

    1. 如果使用logback默认的logback.xml配置文件,将会被过早的加载,无法使用扩展功能。

    2. 这些扩展不能与Logback的配置扫描一起使用。

     

     

    3. 使用SLF4J->Log4j2

    1) 替换为Log4j2日志实现

     

    2) log4j2.xml配置

     

    3) 使用YML或JSON配置(了解)

    当引入 com.fasterxml.jackson.core:jackson-databind 依赖后,可以使用JSON格式来配置Log4j2,默认配置文件名为log4j2.jsn

    当引入 jackson-databind和com.fasterxml.jackson.dataformat:jackson-dataformat-yaml 依赖后,可以使用YML格式来配置Log4j2,默认配置文件名为log4j2.yaml(yml)

     

     

    4. 其它日志配置

    1) 日志组

    可以将一些相关的Logger组合为一个日志组,以便同时对它们进行配置。

    定义后,您可以使用一行配置更改该组中所有Logger的级别:

    为了方便web和sql相关日志的配置,SpringBoot内置了一些日志组:

    NameLoggers
    weborg.springframework.core.codec , org.springframework.http , org.springframework.web
    sqlorg.springframework.jdbc.core , org.hibernate.SQL

     

    2) 颜色编码的输出

    如果终端支持ANSI彩色输出的相关标准,可以通过spring.output.ansi.enabled属性来设置其行为,可选的值有:DETECT(自动检测,默认值)ALWAYSNEVER

    在日志中,可以通过使用%clr转换字来配置颜色编码。转换器以最简单的形式根据对数级别为输出着色,如:%clr(%5p)

    下表描述了日志级别到颜色的对应关系:

    LevelColor
    FATALRed
    ERRORRed
    WARNYellow
    INFOGreen
    DEBUGGreen
    TRACEGreen

    如果需要对某段文本进行特殊的修改,可以使用如下形式:%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow},支持的颜色还有:red、blue、green、yellow、cyan、faint和magenta。

     

     

    第三节 整合JDBC

    1. 基本整合案例

    首先导入整合 JDBC 的依赖:

    再使用spring.datasource.*前缀配置一个数据源:

    SpringBoot会依次查找类路径下的HikariCPTomcat PooledDataSourceCommons DBCP2作为数据源实现,你也可以使用spring.datasource.type属性来显式指定。

    注意:

    1. 如果使用 spring-boot-starter-jdbc 或spring-boot-starter-data-jpa启动器,则会自动获得HikariCP的依赖项。

    2. 通常不需要指定driver-class-name,因为Spring Boot可以从url推导大多数数据库。

    3. 如果未配置spring.datasource.url属性,则Spring Boot会尝试自动配置嵌入式数据库。

    4. 有关更多受支持的选项,请参见DataSourceProperties

    可以在启动类加上@EnableTransactionManagement注解,开启声明式事务控制,之后就可以通过@Transactional(rollbackFor =Exception.class)开事务控制了。

    注意:

    1. 该注解不是必须加的,在自动配置类 TransactionAutoConfiguration 中会默认开启声明式事务。

    此外,SpringBoot会自动查找数据源来配置JdbcTemplateNamedParameterJdbcTemplate,可以直接在代码中注入使用。

    注意:

    1. 当容器中仅存在一个DataSource时(或存在主候选对象),才会配置JdbcTemplate。

    2. 当容器中仅存在一个JdbcTemplate时(或存在主候选对象),才会配置NamedParameterJdbcTemplate。

    您可以使用spring.jdbc.template.*来自定义模板的某些属性,如以下示例所示,其它属性可参考JdbcProperties.Template属性类。

     

     

    2. 通过Bean方法创建数据源

    如果需要自定义数据源(DataSource),可以手动创建一个DataSource实现,然后注入到容器中即可,Spring会在任何需要的地方使用它(包括数据库初始化时)。

    和其它常规Bean一样,可以通过@ConfigurationProperties注解或其它方式来进行外部化配置。

     

    此外,自定义数据源也可以通过Spring提供的DataSourceBuilder工具类创建。

    或可以直接通过DataSourceProperties映射来创建:

     

     

    3. 配置多个数据源

    可以使用同样的方式配置两个数据源,但必须将其中一个标记为@Primary,以便其它地方能够通过类型来获取数据源实例。

    下面是一个外部化配置的示例:

     

     

    4. 其它数据源相关操作

    1) 使用JNDI数据源

    如果您将Spring Boot应用程序部署到应用服务器(如Jboss),则可能需要使用其内置功能来配置和管理数据源,并使用JNDI对其进行访问。

    spring.datasource.jndi-name属性可以替代spring.datasource.url,spring.datasource.username和spring.datasource.password属性,以从特定的 JNDI 位置访问DataSource。

    例如,application.properties中的以下部分显示了如何访问JBoss定义的DataSource:

     

    2) 使用嵌入式数据库

    SpringBoot可以自动配置嵌入式H2,HSQL和Derby数据库,且只需要引入对应依赖即可(无需连接URL、用户名、密码)。

    注意:

    1. 设置spring.datasource.generate-unique-name属性为true,可以确保测试所使用的每个上下文都有一个单独的嵌入式数据库。

    2. spring-boot-starter-data-jpa启动器仅是将嵌入式数据库暂时拉入,你需要spring-jdbc才能自动配置。

    3. 如果自定义嵌入式数据库的连接URL,请确保禁用了数据库的自动关闭功能,而由Spring来进行控制何时关闭。

     

    3) 数据源初始化

    SpringBoot在启动时自动加载CLASSPATH根路径下的schema.sqldata.sql文件,使用默认数据源初始化数据库。

    如果设置了spring.datasource.platform属性(如hsqldb、h2、oracle、mysql、postgresql等),则会加载对应平台的初始化文件,如schema-mysql.sqldata-mysql.sql等。

    注意

    1. 默认情况下,如果初始化错误,则程序将无法启动,你可以通过spring.datasource.continue-on-error属性来修改它。

     

     

    第四节 整合NoSQL

    1. 整合Redis

    Redis提供了丰富的键值缓存和消息代理等功能,SpringBoot为其Lettuce和Jedis客户端提供了基本的自动配置,只需引入spring-boot-starter-data-redis启动器即可。

    需要使用时直接注入RedisConnectionFactoryStringRedisTemplate等类型的示例即可。如果需要自定义一些高级配置,可以分别实现JedisClientConfigurationBuilderCustomizer或LettuceClientConfigurationBuilderCustomizer接口。

     

     

    第五节 整合Junit

    1. SpringBootTest简介

    SpringBootTest将spring-test与Junit、Mockito等主流测试框架进行了整合及自动配置,并提供了一系列的切片测试注解,简化了SpringBoot程序的测试。

     

    2. 整合案例

    1) 引入启动器

     

    2) 编写业务类

     

    3) 编写测试类

     

    3. 其它注解参考

    针对特定场景的测试,只需要加载相对应的Bean即可,SpringBootTest为此提供了许多基于特定场景的测试配置注解,如@JdbcTest、@JsonTest、@DataRedistest、@WebMvcTest等。

     

     

    第六节 整合SpringMVC

    1. 基本整合案例

    注意:

    1. 整合案例的详细步骤请参考“入门案例”章节!

     

     

    2. 配置MVC组件

    1) 配置DispatcherServlet

    DispatcherServlet组件将会被自动配置,默认Servlet上下文根路径为/,可通过spring.mvc.servlet.path=/acme属性进行修改。

    注意:

    1. 如果特别需要,也可以定义自己的DispatcherServlet,但是必须提供DispatcherServletPath指明Servlet上下文根路径。

     

    2) 配置ViewResolver

    SpringBoot将会视情况对如下一些视图解析器进行自动配置:

    注意:

    1. 有关视图解析器配置的更多信息,可参考WebMvcAutoConfiguration、ThymeleafAutoConfiguration等自动配置类。

     

    3) 配置HttpMessageConverter

    HttpMessageConverter用来转换HTTP请求和响应,如将对象自动转换为JSON等,注册方式如下:

     

    4) 配置MessageCodesResolver

    MessageCodesResolver是一个从绑定错误中生成错误码的策略,用于渲染错误信息。如果您设置了spring.mvc.message-codes-resolver.format属性值为 PREFIX_ERROR_CODEPOSTFIX_ERROR_CODE,Spring Boot将为你创建该策略。

     

    5) 配置ConfigurableWebBindingInitializer

    Spring MVC使用WebBindingInitializer来为特定请求初始化WebDataBinder,如果容器中存在自定义的ConfigurableWebBindingInitializer,那么SpringBoot将会优先使用它。

     

    6) 配置Formatter和Converter

     

    7) 配置RequestMappingHandlerMapping

    如果希望提供RequestMappingHandlerMappingRequestMappingHandlerAdapterExceptionHandlerExceptionResolver的自定义实例,则可以声明WebMvcRegistrationsAdapter实例以提供此类组件。

     

    9) 关闭MVC默认配置

    可以在配置类上添加@EnableWebMvc注解,关闭所有默认的MVC配置。

     

     

    3. 静态资源处理

    1) 静态资源路径

    SpringBoot默认从ClassPath中的/static/public/resources/META-INF/resources四个目录查找静态资源,可以通过spring.resources.static-locations属性来进行覆盖。

    此外,Servlet上下文路径/始终将会被当为静态资源路径。

    注意:

    1. 静态资源使用ResourceHttpRequestHandler拦截处理,可以重写WebMvcConfigurer.addResourceHandlers方法来修改。

    2. 如果您的应用程序要包成 jar,请不要使用src/main/webapp目录。虽然此目录是一个通用标准,但它只适用于war打包,如果生成的是一个jar,它将被绝大多数的构建工具所忽略。

     

    2) 静态资源前缀

    默认情况下,请求进来会优先被Controller处理,如果非Controller请求,则会被映射到静态资源处理器,其默认前缀为/**,该前缀可以通过spring.mvc.static-path-pattern属性修改:

     

    3) 欢迎页和页签图标

    Spring Boot 会查找静态资源路径下index.html 文件或 index 模板,如果找到任何一个,则会用作应用程序的欢迎界面。

    同理,也会查找静态路径下的favicon.ico文件,用作程序的页签图标。额外的,如果图标未找到,还会再去查找类路径根目录/

    注意:

    1. 修改静态资源前缀后可能导致欢迎页和页面图标失效。

     

    4) webjars

    Webjars是一种通过Jar包的形式提供前端资源的协议,SpringBoot默认开启对其的支持。如下引入了jquery的Jar包形式,就可以通过http://localhost:8080/webjars/jquery/3.5.1/jquery.js进行访问。

    提示:

    1. 更多webjar可以访问https://www.webjars.org/

     

    5) 静态资源其它配置

    SpringBoot还支持SpringMVC提供的高级资源处理功能,例如静态资源缓存清除或者Webjar的版本无关URL(URL地址自动添加版本号)。

    缓存清除可以通过以下属性配置,它实际是为资源URL添加了一个内容哈希,例如<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>

     

     

    4. 错误页面处理

    1) 默认错误响应

    SpringBoot提供了一个/error映射,用来处理所有的错误响应,并且在servlet容器中注册为"全局"的错误页面。

    你可以通过定义ErrorController(BasicErrorController)ErrorAttributes来修改此默认行为,或使用常规的SpringMVC功能处理,例如@ExceptionHandler@ControllerAdvice

     

    3) 自定义错误页面

    如需修改状态码所对应的错误页面,可在静态资源目录(/public)或模板目录(/templates)下的error文件夹中设置,文件名为对应的状态码或系列掩码。

    如果需要更复杂的状态码-错误页面映射,可以实现ErrorViewResolver接口:

     

     

    5. 文件上传

    1) 上传案例

    前端表单必须为multipart/form-data类型。

     

    SpringBoot在SpringMVC的基础上进一步简化了文件上传,将上传的文件抽象为一个MultipartFile对象。

     

    2) 相关配置

    可以使用spring.servlet.multipart前缀的属性来进行文件上传配置,更多信息可参考MultipartProperties类。

     

     

    6. Json转换

    SpringBoot默认使用Jackson来进行序列化和反序列化JSON数据,可以通过如下方式修改其默认行为。

     

    1) 配置Jackson2ObjectMapperBuilder

    Jackson2ObjectMapperBuilder用于创建ObjectMapper 对象,可通过如下一些属性对其进行配置:

    或通过 Java 代码实现Jackson2ObjectMapperBuilderCustomizer对其进行配置:

    或注册自定义的Jackson2ObjectMapperBuilder来替代它:

     

    2) 配置ObjectMapper

    默认情况下,SpringBoot创建的 ObjectMapper 将默认禁用如下一些选项:

    可以通过@Primary注解,定义一个注入优先级更高ObjectMapper实例来替换它:

    或注册自定义的MappingJackson2HttpMessageConverter,在其中手动创建ObjectMapper对象:

     

    3) 注册JsonSerializer/JsonDeserializer

    JsonSerializerJsonDeserializer用来自定义某些类的序列化和反序列化逻辑,可通过@JsonComponent注解进行注册:

    此外,Spring Boot还提供了JsonObjectSerializerJsonObjectDeserializer用于简化上述自定义序列化和反序列化的代码:

     

    4) Jackson注解

     

     

    7. 原生Servlet组件

    1) 向Web容器注册

    如果需要向Servlet容器注册原生ServletFilterListener等组件,可以使用下面两种方式:

    注意:

    1. 如果是Servlet或Filter组件,还可以借助FilterRegistrationBeanServletRegistrationBean来注册和设置。

    2. @ServletComponentScan在独立容器中无效,而是使用该容器的内置发现机制。

    3. 如果依赖了DataSource等其它配置,最好是在初次使用时才进行初始化。

     

    2) 映射规则

    默认情况下,如果上下文仅包含一个Servlet,那么将会映射到/,如果有多个Servlet,那么将会使用其Bean名称作为路径前缀。

    对于过滤器,将会始终映射到/*。SpringBoot为多种场景所使用的过滤器做了自动配置,下面是一个清单:

    Servlet FilterOrder
    OrderedCharacterEncodingFilterOrdered.HIGHEST_PRECEDENC
    WebMvcMetricsFilterOrdered.HIGHEST_PRECEDENCE + 1
    ErrorPageFilterOrdered.HIGHEST_PRECEDENCE + 1
    HttpTraceFilterOrdered.LOWEST_PRECEDENCE - 10

    注意:

    1. 这些映射规则可以通过ServletRegistrationBean、FilterRegistrationBean和ServletListenerRegistrationBean来完全控制。

     

     

    3) 禁止注册

    如果不想容器中的某个组件向Web服务器注册,则必须显式声明禁止注册。

     

     

    8. 其它自动配置

    1) CROS配置

    跨域资源共享(Cross-origin resource sharing,CORS)是大多数浏览器实现的一个W3C规范,其可允许您以灵活的方式指定何种跨域请求可以被授权,而不是使用一些不太安全和不太强大的方式(比如IFRAME或者JSONP)。

    可在控制器方法上使用@CrossOrigin注解使当前资源支持CORS:

    或通过重写WebMvcConfigureraddCorsMappings(CorsRegistry)方法来定义全局CORS配置:

     

    2) 模板引擎

    SpringBoot为FreeMarker、Thymeleaf、Groovy、Mustache、JSP等模板技术提供了自动配置(对应的视图解析器等),默认从src/main/resources/templates目录查找模板文件。

    注意:

    1. 尽量不要使用JSP作为SpringBoot的模板引擎,它和嵌入式容器一起使用时会有一些问题。

     

    3) 内容协商

    SpringMVC 通过解析请求路径将请求映射到不同的控制器方法,但 SpringBoot 默认禁用了其后缀模式匹配

    这意味着GET /projects/spring-boot.json之类的请求将不会与@GetMapping("/projects/spring-boot")所注解的方法相匹配,因为如今基于Accept请求头的内容协商已变得非常可靠。

    除此之外,你也可以通过URL参数的形式附带内容信息,如GET /projects/spring-boot?format=json,开启该功能的配置如下:

    如果你了解所有注意事项后,仍然希望开启后缀模式匹配,可以使用下面配置:

     

    4) RestTemplate

    可通过注入RestTemplateBuilder来快速创建RestTemplate实例,并对其进行必要的配置:

    可以实现RestTemplateCustomizer接口,对RestTemplateBuilder创建的RestTemplate进行统一配置:

    注意

    1. 你也可以创建自己的RestTemplateBuilder来实现更多配置,但此时RestTemplateCustomizer将不会被自动注册。

     

     

    第七节 整合消息队列

    1. JMS(ActiveMQ)

    2. AMQP(RabbitMQ)

    3. Kafka

     

     

    第八节 其它技术整合

    1. 整合JSON

    Spring提供了三个JSON库的默认配置:Jackson(默认)、Gson、JSON-B,当类路径下存在对应的Jar包时,将会开启使用。

     

    2. 整合异步任务

    SpringBoot中通过@EnableAsync注解开启异步任务支持:

    通过@Async注解标记方法为异步方法:

    当该方法被 Spring 创建的代理类对象调用时,就会异步执行。

     

    3. 整合定时任务

     

    4. 整合邮件

     

     

    第04章_SpringBoot扩展

    第一节 SpringBoot Actuator

    1. Actuator简介

    1) Actuator和EndPoint

    SpringBoot Actuator可以方便的监视管理你的生产应用程序,并自动配置审计、运行状况、Metrics收集等。

    EndPoint(端点)是 Actuator 与生产应用程序的交互点,常见端点如下:

    端点ID说明
    auditevents公开当前应用程序的审核事件信息
    beans显示应用程序中所有SpringBean的完整列表
    caches公开可用的缓存
    conditions显示在配置和自动配置类上评估的条件以及它们匹配或不匹配的原因
    configprops显示所有@ConfigurationProperties的整理列表
    env从Spring的ConfigurableEnvironment公开属性
    flyway显示已应用的所有Flyway数据库迁移
    health显示应用程序运行状况信息
    httptrace显示HTTP跟踪信息(默认情况下,最近100个HTTP请求-响应交换)
    info显示任意应用程序信息
    integrationgraph显示Spring Integration图
    loggers显示和修改应用程序中Logger的配置
    liquibase显示已应用的所有Liquibase数据库迁移
    metrics显示当前应用程序的“Metrics”信息
    mappings显示所有@RequestMapping路径的整理列表
    scheduledtasks显示应用程序中的计划任务。
    sessions允许从Spring Session支持的会话存储中检索和删除用户会话(不适用WebFlux)。
    shutdown使应用程序正常关闭
    threaddump执行线程转储

    如果是Web应用程序(Spring MVC/Spring WebFlux/Jersey),则还提供以下附加端点:

    端点ID说明
    heapdump返回一个hprof堆转储文件。
    jolokia通过HTTP公开JMX bean(当 Jolokia在Classpath上时,不适用于WebFlux)。
    logfile返回日志文件的内容(如果已设置logging.file或logging.path属性)。支持使用 HTTP Range Headers 来检索部分日志文件。
    prometheus以Prometheus服务器可以抓取的格式公开Metrics。

    提示

    1. 关于EndPoint的更多信息以及EndPoint的请求和响应格式,请参阅单独的API文档

     

    2) health端点简介

    health端点公开了HealthIndicator收集的基本运行状况信息,监视软件一般通过它来判断系统是否发生故障,常见健康指示器如下:

    NameDescription
    DiskSpaceHealthIndicator检查磁盘空间是否不足
    DataSourceHealthIndicator检查是否可以创建DataSource的连接
    ElasticsearchHealthIndicator检查Elasticsearch集群是否已启动
    MailHealthIndicator检查邮件服务器是否已启动
    MongoHealthIndicator检查Mongo数据库是否已启动
    RabbitHealthIndicator检查Rabbit服务器是否已启动
    RedisHealthIndicator检查Redis服务器是否启动

    可通过如下一些属性进行配置:

    注意:

    1. HealthAggregator会对所有HealthIndicator 收集的运行状况信息由进行聚合,通过HealthIndicatorRegistry在运行时注册和注销健康指示器。

    2. 可以通过management.health.defaults.enabled属性将上述指示器全部禁用。

     

    可以通过实现HealthIndicator接口来自定义健康指示器,标识符默认为不带HealthIndicator后缀的Bean名称。

    一般来说,都会为健康指示器的返回值设置健康状态,内置的健康状态有如下一些:

    StatusMapping
    DOWNSERVICE_UNAVAILABLE(503)
    OUT_OF_SERVICESERVICE_UNAVAILABLE(503)
    UP默认情况下没有Map,http 状态为 200
    UNKNOWN默认情况下没有Map,http 状态为 200

    注意:

    1. 如需自定义其它健康状态(如FATAL)或修改HTTP响应状态码,可使用HealthStatusHttpMapper类。

     

    3) info端点简介

    info端点公开了程序上下文中InfoContributor所收集的各种信息,常见的信息贡献者如下:

    NameDescription
    EnvironmentInfoContributor公开Environment中的任何key
    GitInfoContributor如果git.properties文件可用,则公开git信息git.branch/git.commit.id/git.commit.time
    BuildInfoContributor如果META-INF/build-info.properties文件可用,则公开构建信息

    可通过如下一些属性进行配置:

    注意:

    1. 可以通过management.info.defaults.enabled属性将上述信息贡献者全部禁用。

     

    可以通过实现InfoContributor接口来自定义信息贡献者。

    如果到达info端点,则应该看到包含以下附加条目的响应:

     

    4) loggers端点简介

    loggers端点可以在运行时查看和配置应用程序的日志级别。

    如通过/loggers路径查看所有的日志级别,通过/loggers/root路径查看root logger的日志级别信息。

    要修改为指定的日志级别,请使用POST方式并附带请求体参数,如下修改root logger的日志级别为DEBUG。

    注意:

    1. 日志级别可以是TRACE、DEBUG、INFO、WARN、ERROR、FATAL、OFF、null(没有显式配置)等。

     

    5) httptrace端点

    httptrace端点将会跟踪最近100次请求-响应交换的基本信息,并存储到InMemoryHttpTraceRepository中,其基本配置可通过management.trace.http.include属性来调整。

    如需进行高级的定义,请定义自己的HttpExchangeTracer、InMemoryHttpTraceRepository或HttpTraceRepository实现。

     

     

    2. 启用和公开端点

    1) 启用端点

    默认情况下,除shutdown之外的所有端点都处于启用状态,如需启用或禁用某个端点,可以设置其enabled属性。

    如需批量设置,可以通过management.endpoints.enabled-by-default修改端点是否启用的默认值。

    注意:

    1. 禁用的端点将从应用程序中完全删除,如果您只想修改端点是否公开,请使用参考下一小节。

     

    2) 公开端点

    端点只有公开后才能被访问,如需公开或关闭某个端点,请使用下面特定于公开方式的includeexclude属性:

    属性默认值说明
    management.endpoints.jmx.exposure.exclude JMX方式关闭的端点
    management.endpoints.jmx.exposure.include*JMX方式公开的端点
    management.endpoints.web.exposure.exclude HTTP方式关闭的端点
    management.endpoints.web.exposure.includeinfo, healthHTTP方式公开的端点

    下面一些使用案例:

    注意:

    1. 如需更加精细的控制端点的公开时间,可以继承EndpointFilter接口来进行扩展。

     

     

    3. 访问端点

    1) HTTP方式访问端点

    HTTP端点访问路径前缀+端点映射路径组成,前缀默认为/actuator,端点映射路径默认为端点id

    例如health端点默认通过/actuator/health进行访问。

    注意:

    1. 前缀是相对于server.servlet.context-path的,但如果配置了management.server.port,则相对于management.server.servlet.context-path

     

    注意:

    1. 仅当端口与主服务器端口不同时,您才能在其他地址上侦听!

     

    默认情况下,管理服务器与主应用程序使用相同的SSL配置,但如果自定义了管理服务器端口,则可以分别进行配置。

     

    由于端点暴露信息的敏感性,你应该像其它敏感URL一样,保护HTTP端点的安全,使用 Spring Security 时的参考配置如下:

    如果允许未经身份验证的端点访问,可以配置如下:

     

    如果使用Spring MVC或Spring WebFlux,可以通过下面方式支持HTTP端点的CROS。

    有关选项的完整列表,请参见CorsEndpointProperties

     

    如果您不想通过HTTP方式公开端点,则可以将Management端口设置为-1:

    或使用management.endpoints.web.exposure.exclude属性关闭所有HTTP端点:

     

    2) JMX方式访问端点

    MBean名称端点id生成,例如health端点公开为org.springframework.boot:type=Endpoint,name=Health。但是,当应用程序包含多个ApplicationContext时,可能会出现名称冲突,可通过下面属性生成唯一的MBean名称。

     

    默认情况下,SpringBoot将Management端点暴露在org.springframework.boot域下,可通过下面属性进行修改。

     

    Jolokia(JMX-HTTP bridge)可以让你以HTTP方式访问JMX Bean。首先导入依赖如下:

    再通过management.endpoints.web.exposure.include=jolokia来暴露Jolokia端点,然后就可以通过/actuator/jolokia来访问它。

     

     

     

    3) 隐藏敏感信息

     

     

    4. 自定义端点

    1) @Endpoint

    使用@Endpoint注解可以将Bean声明为一个端点:

    特别的,对于 Web 端点,可使用@WebEndpoint@EndpointWebExtension进行定义:

    注意:

    1. 对于JMX 端点,也可使用@JmxEndpoint@EndpointJmxExtension进行定义。

    2. 可以通过@ServletEndpoint注解将Servlet公开为端点,但其与Servlet容器深度集成,可移植性差,不推荐使用。

     

    2) 端点参数

    端点支持接收简单类型的参数,HTTP端点通过URL查询参数或JSON格式的请求体参数传入,JMX端点通过MBean传入,示例如下:

    对于Web端点,还可使用@Selector注解方法参数,将其标识为路径变量,效果与Spring MVC的@PathVariable注解类似。

    注意:

    1. 参数映射要求开启Java的-parameters编译参数,如果使用了SpringBoot父工程和Maven插件,将会自动开启。

    2. 如果类型不匹配,将会使用ApplicationConversionService实例进行类型转换,转换失败则响应400(错误请求)。

    3. 默认情况下,端点参数都是必选项,可以通过@org.springframework.lang.Nullable注解是其变为可选。

     

    3) Controller端点

    @ControllerEndpoint@RestControllerEndpoint用于公开特定于Spring Web框架的端点,其使用@GetMapping、@PostMapping、@DeleteMapping、@RequestMapping等Spring MVC/Spring WebFlux的标准注解进行方法和参数的映射。

    注意:

    1. @RestControllerEndpoint不会注册Bean,仍需要添加@Component注解。

    2. Controller端点提供了与Spring Web框架的更深层集成,但可移植性变差。因此,尽可能使用@Endpoint和@WebEndpoint注解。

     

     

    5. Micrometer

    1) Micrometer简介

    Micrometer是Java平台上的一种通用应用程序指标接口,类似于日志体系中的SLF4J,它提供了Timers、Guauges、Counters等多种度量指标类型,并支持Elastic、Influx、JMX、Prometheus等众多的监视系统。

    Micrometer中有两个最核心的概念,分别是计量器(Meter)计量器注册表(MeterRegistry)。其中计量器用来收集不同类型的性能指标信息,Micrometer提供了如下几种不同类型的计量器:

    SpringBoot Actuator内置了Micrometer依赖,并自动配置CompositeMeterRegistry,查找类路径下支持的计量器注册表(MeterRegistry),这些计量器注册表由micrometer-registry-Xxxx依赖引入。

    下面是一些相关的属性配置:

    您可以注册任意数量的MeterRegistryCustomizer来进一步配置计量器注册表,例如在向计量器注册表注册任何计量器之前应用通用标签(tag):

    完成计量器注册表配置后,可以通过注入的方式获取计量器注册表并注册计量器,如下注册一个 Counter 类型的计量器统计core接口的访问次数。

    提示:可以通过MeterBinder来向Spring管理的MeterRegistry自动注册Metrics。

     

    2) 支持的监视系统

    SpringBoot Actuator支持将指标数据导出到众多的监视系统,如导出到本地的Elastic,配置如下:

    或者通过提供/actuator/prometheus端点(默认关闭)的方式让Prometheus主动获取监控数据:

    更多监视系统配置请参考相应的官方文档!

     

    3) 支持的指标(Metrics)

    SpringBoot将根据当前环境配置如下一些核心Metrics:

     

    4) 配置计量器(Meter)

    注意:如果使用Graphite,则通用标签的顺序很重要,由于使用这种方法不能保证通用标签的顺序,因此建议Graphite用户定义自定义MeterFilter。

     

    可以通过io.micrometer.core.instrument.config.MeterFilter接口配置Meter,如将所有ID以com.example开头的Meter的mytag.region标签重命名为mytag.area:

     

    5) Metrics端点

    Metrics端点可用于诊断检查应用程序收集的Metrics,如/actuator/metrics将显示可用监视系统的名称列表,/actuator/metrics/jvm.memory.max将显示JMX监视器的信息。

    如果需要更加深入的了解相应的监视信息,可以通过tag=KEY:VALUE形式的查询参数,如/actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace。

     

     

     

    第二节 SpringBoot开发套件

    1. Developer Tools

    1) Developer Tools简介

    Spring Boot Developer Tools在开发阶段提供了一些额外的功能,如默认属性全局配置自动重启远程调试和更新等,解决开发中的一些繁琐问题。如果需要使用,可以通过如下依赖来引入:

    注意:

    1. 开发者工具仅适用于开发或测试环境,当使用java -jar 命令启动,或使用特殊的类加载器启动时被视为“完全打包”的应用程序,开发者工具将会被移除。

     

    2) 默认属性

    开发者工具修改了一些默认属性,使其更适用于开发和测试环境,如通过在application.properties中添加配置spring.thymeleaf.cache=false为thymeleaf禁用默认的缓存等。

    注意:

    1. 开发者工具的所有默认属性可在DevToolsPropertyDefaultsPostProcessor查找。

    2. 如果想禁用默认属性,可配置spring.devtools.add-properties属性为false。

     

    3) 全局配置

    开发者工具会自动扫描HOME目录下的.spring-boot-devtools.properties文件,读取其中的全局配置,并且优先采用。

    注意:

    1. 如果是windows用户,可能需要设置一个环境变量HOME

     

    4) 自动重启

    开发者工具为应用创建两个类加载器,分别是加载不变类(例如来自第三方jar的类)的基础类加载器和加载可变类(当前正在开发的类)的重启类加载器。当classpath上有文件被修改时,程序将自动重启,并创建新的重启类加载器。这种方式相较于应用平时使用的“冷启动”要快得多,毕竟基础类加载器已经处于可用的状态。关于详细配置请参考官方文档!

    注意:

    1. 如果想体验更加强大的"热部署"功能,推荐使用商业软件Jrebel

     

    5) 远程调试和更新

    开发者工具支持远程调试功能,详细配置请参考官方文档!

     

     

    2. Spring Initializer

    Spring Initializer是一个创建SpringBoot项目的快速向导,它根据用户所选择的场景,自动引入对应的场景启动器,并进行一些基础配置。

     

     

    3. SpringBoot Cli

    Spring Boot CLI 是一个命令行工具,用于运行Groovy脚本,快速开发SpringBoot应用程序。更多资料请参考官方文档!

     

     

    第三节 SpringBoot相关插件

    1. SpringBoot Maven Plugin

    SpringBoot Maven Plugin在Maven打包SpringBoot应用时提供了一些额外的支持,如下是它的功能列表:

    GoalDescription
    spring-boot:repackage重新打包为可执行的Jar包或war包
    spring-boot:run本地运行应用程序
    spring-boot:build-info基于当前MavenProject的内容生成build-info.properties信息
    spring-boot:build-image使用buildpack将应用程序打包到OCI映像中
    spring-boot:start启动一个应用程序,一般在集成测试之前执行
    spring-boot:stop停止由start启动的程序,一般在集成测试之后执行
    spring-boot:help在终端显示插件的帮助信息,如mvn spring-boot:help -Ddetail=true -Dgoal=<goal-name>

     

    1) 重新打包(repackage)

    重新打包(repackage)功能可以将当前项目代码及所有依赖项打包为一个可执行的Jar包,下面是一个较完整的配置示例:

    注意

    1. 更多属性和分层打包请参考官方文档:https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#goals-repackage

    2. 分层打包也可以使用maven-assembly-plugin插件。

     

    2) 生成build-info

    如果SpringBoot Maven Plugin包含build-info目标,则在执行Maven打包时,自动生成META-INF/build-info.properties文件。

    当项目引入了spring-boot-starter-actuator启动器时,可以访问http://localhost:8080/actuactor/info来查看编译信息。

    image-20220719150211544

     

     

    3) 本地运行

    SpringBoot Maven Plugin的run目标可以在本地启动SpringBoot应用程序,并自定义JVM参数、系统属性、环境变量、程序参数和profile等。

    更多资料请查阅官方文档:https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#run

     

    4) 跳过测试

    本节请查阅官方文档:https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#integration-tests

    如果需要在打包时跳过测试,可使用如下几种方式:

     

     

    5) 打包为OCI镜像

    本节请查阅官方文档:https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#build-image

     

     

    2. maven-resources-plugin

    继承自spring-boot-starter-parent的项目,可以在**/application*.yml(yaml/properties)中通过@...@占位符的方式来使用Maven中的扩展属性。

    如果没有继承spring-boot-starter-parent,我们需要手动配置这个过滤和扩展。

    如果需要使用${variable.name}类型的标准占位符,我们需要将useDefaultDelimeters设置为true,并且您的application.properties将如下所示: