欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

跟着官方文档学 SpringBoot 三:spring boot 特性

程序员文章站 2022-07-10 15:04:04
...

 

spring boot 特性

【启动相关】

 

1. 启动应用

在启动应用类的 main 方法中调用 SpringApplication 的 run():

public static void main(String[] args) {
	SpringApplication.run(MySpringConfiguration.class, args);
}

 

2. 启动失败

如果应用启动失败了,FailureAnalyzers 会获取错误信息,并得到一个具体解决该问题的办法。

比如,8080 端口被占用,你可能会看到如下信息:

***************************
APPLICATION FAILED TO START
***************************

Description:

Embedded servlet container failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

 如何创建自己的失败分析器?

1)创建一个自定义的失败分析类,继承 AbstractFailureAnalyzer。如果自己无法处理异常问题,可以通过返回 null 来让其他实现类来处理;

2)在 META/spring.factories 文件中注册该类,如下:

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer

 如果需要访问 BeanFactory 或者 Environment,那么自定义的 FailureAnalyzer 可以通过实现 BeanFactoryAware 或者 EnvironmentAware 接口。

 

3. 定制 Banner

Banner,即应用启动时的图像,默认为 spring boot:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::   v2.0.0.RELEASE

 通过在 classpath(比如在 resources 文件夹下) 添加一个 banner.txt 或者 在配置文件中设置 spring.banner.location 属性指定文件位置。如果文件的编码不是 UTF-8,那么需要设置 spring.banner.charset 指定编码。

 

除了添加文本文件,也可以添加 banner.gif,banner.jpg 或者 banner.png 的图片,或者设置 spring.banner.image.location 属性指定文件位置,图片会被转换为 ASCII 码的表现形式打印。

博主在 resources 下 添加了 banner.png :

 
跟着官方文档学 SpringBoot 三:spring boot 特性
            
    
    博客分类: SpringBoot spring bootjavaspringbootSpringBootJava 

启动应用后,显示效果:

 
跟着官方文档学 SpringBoot 三:spring boot 特性
            
    
    博客分类: SpringBoot spring bootjavaspringbootSpringBootJava 

 

延伸:什么是 classpath?

虽然,classpath 这个词翻译为中文,大家都知道,叫做“类路径”,那么究竟什么是类路径呢?想必许多同学和我一样曾经被困扰过。

classpath 指的是程序编译后 classes(类的字节码文件)所在的目录。在程序没有编译前,通常 .java 文件放置于 java 文件夹下(比如 src/main/java/service/UserService.java),而配置文件通常位于 resources 文件夹下(比如 src/main/resources/application.properties)。当程序编译后,java 文件夹下的 .java 文件会变为 target/classes 文夹下的.class 文件,resources 文件夹下的文件也会被置于 classes 文件夹下,此时的 classes 文件夹即项目的 classpath。

 

如果将 banner.txt 或者 banner.png 直接放置于 src/main/java 文件夹下,由于编译后不在 target/classes 文件夹下,因而是不会生效的。(IntelliJ IDEA 工具编译后的文件都在 target 目录下)

 

4. 定制 SpringApplication

当你觉得默认的 SpringApplication 无法满足使用时,可以通过创建一个本地(相对于 spring-boot-starter 而言)的实例来定制它。

比如,上一小节的定制 Banner 同样可以通过编程的方式实现:

public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Example.class);
        application.setBanner(new MyBanner());
        application.run(args);
}

 也可以关闭它:

public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Example.class);
        application.setBannerMode(Banner.Mode.OFF);
        application.run(args);
}

 

5. 流式 API

通过 SpringApplicationBuilder 对象可以实现链式调用多个方法,并且创建一个分层次的应用上下文环境:

new SpringApplicationBuilder()
		.sources(Parent.class)
		.child(Application.class)
		.bannerMode(Banner.Mode.OFF)
		.run(args);

 在创建分层的 应用上下文时需要注意一些限制,比如 Web 组件必须包含在子上下文中,并且子上下文和父上下文必须使用同一个 Environment。

 

6. 事件和监听器

一些事件是在 ApplicationContext 创建之前被触发的,因此无法在这些事件上注册 listener 作为一个 @Bean。可以通过 SpringApplication.addListeners() 或者 SpringApplicationBuilder.listeners() 方法进行注册;如果想要这些 listeners 自动注册,而不关心应用的创建方式,可以添加 META-INF/spring.factories 文件,通过如下示例方式注册 listener:

org.springframework.context.ApplicationListener=com.example.project.MyListener

 

7. Web 环境

SpringApplication 会尝试创建正确类型的 ApplicationContext,默认情况下使用 AnnotationConfigApplicationContext 或者 AnnotationConfigServletWebServerApplicationContext,

这基于正在开发的是否为一个 web 应用。判断一个环境是否为 web 环境的算法是相当简单的,基于几个类是否存在而已。如果想要覆盖它判断环境类型的方式,

可以通过 setWebEnvironment(boolean webEnvironment)设置。通过调用 setApplicationContextClass() 方法可以自己控制 ApplicationContext。在 JUnit 测试环境下使用 SpringApplication时,推荐调用 setWebEnvironment(false) 方法。

 

8. 访问应用参数

如果需要访问那些被传递进 SpringApplication.run() 方法的参数,可以通过注入一个 org.springframework.boot.ApplicationArguments bean。ApplicationArguments 接口提供了访问原生的 String[] 参数和被解析为 option 和 non-option 的参数,如下所示:

 

import org.springframework.boot.*
import org.springframework.beans.factory.annotation.*
import org.springframework.stereotype.*

@Component
public class MyBean {

	@Autowired
	public MyBean(ApplicationArguments args) {
		boolean debug = args.containsOption("debug");
		List<String> files = args.getNonOptionArgs();
		// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
	}

}
 Spring Boot 还向 Spring 环境注册了一个 CommandLinePropertySource。这使得可以通过使用 @Value 注释来注入单个应用程序参数。

 

 

9 使用 ApplicationRunner 或者 CommandLineRunner

如果有一些特殊的代码需要在 SpringApplication 启动完成之前运行,那么可以通过实现 ApplicationRunner 或者 CommandLineRunner 接口来完成。这两个接口运行的方式都是一样的,

并且提供单一的 run 方法,run 方法会在 SpringApplication.run() 完成之前被调用。

 

CommandLineRunner 接口将应用参数当作简单的 string 数组进行访问,如下示例:

 

import org.springframework.boot.*
import org.springframework.stereotype.*

@Component
public class MyBean implements CommandLineRunner {

	public void run(String... args) {
		// Do something...
	}

}
 如果定义了多个 CommandLineRunner 或者 ApplicationRunner beans,那么它们必须根据特定的顺序被调用。

 

可以通过额外实现 org.springframework.core.Ordered 接口,或者使用 org.springframework.core.annotation.Order 注解完成顺序调用。

 

10. 退出应用

每个 SpringApplication 都向 JVM 注册了一个关闭的钩子(hook),以确保在退出的时候优雅地关闭 ApplicationContext 。所有的 Spring 标准生命周期的回调都可以使用,比如 DisposableBean 接口或者 @PreDestroy 注解。

 

此外,如果希望在 SpringApplication.exit() 被调用前执行一段特定的退出代码(exit code),那么这些 beans 可以通过实现 org.springframework.boot.ExitCodeGenerator 接口完成。

这些特定的退出代码会被传递至 System.exit() 用来作为状态码返回,如下示例:

@SpringBootApplication
public class ExitCodeApplication {

	@Bean
	public ExitCodeGenerator exitCodeGenerator() {
		return () -> 42;
	}

	public static void main(String[] args) {
		System.exit(SpringApplication
				.exit(SpringApplication.run(ExitCodeApplication.class, args)));
	}

}

 并且,异常类可以通过实现 ExitCodeGenerator 接口和实现 getExitCode()方法,在异常发生时,可以返回退出代码。

 

11. 管理员特性

通过指定 spring.application.admin.enabled 属性为 true(false)启用(不启用)管理员相关特性,这会将 SpringApplicationAdminMXBean 暴露在 MBeanServer 平台。可以通过使用这个特性远程管理 spring boot 应用,这对于服务包装实现很有用。

 

 

【外部化配置】

 

springboot 可以外部化配置,使得相同的代码可以适应不同的环境。简单讲,就是从外部的配置文件获取指定值,不写死代码。

使用 properties 文件、YAML 文件、环境变量、命令行参数这几种方式进行配置。这些配置的属性值可以通过 @Value 注解直接注入到 bean 中,可以通过 Spring 的 Environment 接口实现类来访问,

或者通过 @ConfigurationProperties 绑定到结构化对象。

 

为了实现属性值的合理的覆盖(因为配置方式有多种,可能存在键重复值覆盖),springboot 使用了一种特殊的顺序。属性将按以下顺序读取:

1. Devtools 全局设置。(当开启了 devtools 的情况下,在 ~/ .spring-boot-devtools.properties 配置)

2. 测试类中 @TestPropertySource 注解中的属性值

3. 测试类中 @SpringBootTest#properties 注解中的属性值

4. 命令行参数

5. SPRING_APPLICATION_JSON 的属性值(内嵌在环境变量或系统属性中的JSON)

6. ServletConfig 初始化参数

7. ServletContext 初始化参数

8. 来自 java:comp/env 的 JNDI 属性

9. Java 系统属性值(通过 System.getProperties() 获取的值)

10. 操作系统环境变量

11. RandomValuePropertySource 中有属性值的,并且符合 random.* 格式

12. 没被打进 jar 包的 profile-specific 应用属性(application-{profile}.properties 和 YAML 变量)

13. 被打进 jar 包的应用属性(application-{profile}.properties 和 YAML 变量)

14. 没被打进 jar 包的应用属性(application-{profile}.properties 和 YAML 变量)

15. 被打进 jar 包的应用属性(application-{profile}.properties 和 YAML 变量)

16. 在 @configuration 类上的 @PropertySource 注解属性

17. 默认属性(通过设置 SpringApplication.setDefaultProperties 指定的)

 

在举具体的示例之前,推荐先写一个使用了 name 属性值的组件(@Component),如下:

import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*

@Component
public class MyBean {

    @Value("${name}")
    private String name;

    // ...

}

 在 classpath (比如 resources 资源文件夹)中添加一个“application.properties”属性文件,在文件中指定 name 的值,如 name=Lina。

 对于一次性测试,可以在命令行中进行指定,比如:

java -jar app.jar --name="Spring"
 

 

SPRING_APPLICATION_JSON 的属性值可以通过环境变量的方式应用于命令行:

1. 在 UNIX shell 中可以使用如下命令:

$ SPRING_APPLICATION_JSON='{"acme":{"name":"test"}}' java -jar myapp.jar
 该命令表示 在 spring 中 acme.name 对应的属性值为 test。

 

2. 在系统属性(System property)中将 JSON 作为 spring.application.json 使用:

 

$ java -Dspring.application.json='{"name":"test"}' -jar myapp.jar
        3. 通过使用命令行参数来使用 JSON:
$ java -jar myapp.jar --spring.application.json='{"name":"test"}'
        4. 将 JSON 作为一个 JNDI 变量:
java:comp/env/spring.application.json
        
1. 配置随机属性值
对于注入随机值来说, RandomValuePropertySource 很有用。它能产生 integers, longs, uuids, 或者 strings:
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
 
2. 访问命令行属性值
默认情况下,SpringApplication 会将所有的命令行参数(以 -- 开头,如 --server.port=9000)转换为一个 property,并添加到 spring 环境中。
注意一下,命令行的属性值相对来说优先级是比较高的(排第四)。如果不想要将命令行参数作为属性值放入 spring 中,可以如下设置来关闭:
SpringApplication.setAddCommandLineProperties(false)
 
3. Application Property 文件
SpringApplication 从如下位置中的 application.properties 文件加载属性:
1) 当前目录下的 /config 目录中(经测试,文档中的“当前目录”为项目根目录,即与 src 同级目录。汗...)
2) 当前目录中(项目根目录)
3) classpath 里的 /config 目录下
4)classpath 根目录下
加载的优先级即以上排列的顺序。
如果不想将属性文件命名为“application.properties”,可以通过指定一个叫做 spring.config.name 的环境属性,比如:
// 设置命令行参数的方式
$ java -jar myproject.jar --spring.config.name=myproject
如果不想属性文件必须在默认读取的位置,可以如下自定义位置(示例指定了两个位置):
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
 注意:由于为了决定那个文件必须被加载, spring.config.name 和 spring.config.location 这两个属性将会被很早使用,因此它们必须在环境属性中定义,比如定义在操作系统环境变量中,系统属性中或者命令行参数中。
如果 spring.config.location 对应的文件是一个目录(directory),那么必须以“/”结尾,这样它会和 spring.config.name 组合起来形成具体文件路径。
4. profile

啥是 spring-boot 的 profile? profile 的中文意思大体上是用于描述一个人的生活,工作或性格等,就是一个简要的概括,具体可以点这里查看英文释义,在spring-boot 中 一个 profile 概括了一个配置文件的使用环境,比如开发环境配置,生产环境配置等,激活不同的 profile,表示使用不同的配置参数。
读取 application-{profile}.properties 文件的位置与 application.properties 相同,不过特定属性文件中数据的优先级总是高于 application.properties 中定义的。如果多个(相同的)特定属性文件被指定,那么后加载的生效。
比如,spring.profiles.active 属性指定的文件在使用 SpringApplication API 配置的文件之后添加,因此 spring.profiles.active 属性指定的具有更高优先级。
5. 属性文件中的占位符
在 application.properties 文件中先定义的属性,可以供后定义的属性使用:
app.name=MyApp
app.description=${app.name} is a Spring Boot application
 
 后续的 spring boot 特性,请见“spring boot 特性之...”系列!
 
 
 
 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 跟着官方文档学 SpringBoot 三:spring boot 特性
            
    
    博客分类: SpringBoot spring bootjavaspringbootSpringBootJava 
  • 大小: 13 KB
  • 跟着官方文档学 SpringBoot 三:spring boot 特性
            
    
    博客分类: SpringBoot spring bootjavaspringbootSpringBootJava 
  • 大小: 11.9 KB