1.简介
1.1 概述
The banner that is printed on start up can be changed by adding a
banner.txt
file to your classpath or by setting thespring.banner.location
property to the location of such a file. If the file has an encoding other than UTF-8, you can setspring.banner.charset
. In addition to a text file, you can also add abanner.gif
,banner.jpg
, orbanner.png
image file to your classpath or set thespring.banner.image.location
property. Images are converted into an ASCII art representation and printed above any text banner.
banner 是在启动时打印的内容,可以通过在 classpath 下添加 “ banner.txt” 文件或 设置“ spring.banner.location” 属性值来改变 banner 的内容。如果文件的编码不是UTF-8,则可以通过spring.banner.charset
进行设置。除了文本文件之外,您还可以在 classpath 下添加 banner.gif
,banner.jpg
或 banner.png
图像文件或设置 spring.banner.image.location
属性。图片将被转换为 ASCII 的形式进行展现并在文本内容之前打印。
1.2 特点
banner.txt 可以包含如下内容
Variable | Description |
---|---|
${application.version} |
The version number of your application, as declared in MANIFEST.MF . For example, Implementation-Version: 1.0 is printed as 1.0 . |
${application.formatted-version} |
The version number of your application, as declared in MANIFEST.MF and formatted for display (surrounded with brackets and prefixed with v ). For example (v1.0) . |
${spring-boot.version} |
The Spring Boot version that you are using. For example 2.2.8.RELEASE . |
${spring-boot.formatted-version} |
The Spring Boot version that you are using, formatted for display (surrounded with brackets and prefixed with v ). For example (v2.2.8.RELEASE) . |
${Ansi.NAME} (or ${AnsiColor.NAME} , ${AnsiBackground.NAME} , ${AnsiStyle.NAME} ) |
Where NAME is the name of an ANSI escape code. See AnsiPropertySource for details. |
${application.title} |
The title of your application, as declared in MANIFEST.MF . For example Implementation-Title: MyApp is printed as MyApp . |
The
SpringApplication.setBanner(…)
method can be used if you want to generate a banner programmatically. Use theorg.springframework.boot.Banner
interface and implement your ownprintBanner()
method.You can also use the
spring.main.banner-mode
property to determine if the banner has to be printed onSystem.out
(console
), sent to the configured logger (log
), or not produced at all (off
).
2.演示环境
- JDK 1.8.0_201
- Spring Boot 2.2.0.RELEASE、Spring Cloud Hoxton.RELEASE
- 构建工具(apache maven 3.6.3)
- 开发工具(IntelliJ IDEA )
3.演示代码
3.1 代码说明
自定义 banner.txt,在项目启动时打印自定义 banner
3.2 代码结构
3.3 maven 依赖
<dependencies>
<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>
</dependency>
</dependencies>
3.4 配置文件
application.properties
application.version=0.0.1-SNAPSHOT
application.formatted-version=0.0.1
application.title=spring-boot-banner
banner.txt
${application.version}
${application.formatted-version}
${application.title}
${AnsiColor.BRIGHT_GREEN}$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
${AnsiColor.BRIGHT_CYAN}$$ _________ __ __/ / /_ ____ _/ / /___ _____/ / $$
${AnsiColor.BRIGHT_CYAN}$$ / ___/ __ / / / / / __ / __ `/ / / __ `/ __ / $$
${AnsiColor.BRIGHT_CYAN}$$ (__ ) /_/ / /_/ / / /_/ / /_/ / / / /_/ / /_/ / $$
${AnsiColor.BRIGHT_CYAN}$$ /____/\____/\__,_/_/_.___/\__,_/_/_/\__,_/\__,_/ $$
${AnsiColor.BRIGHT_GREEN}$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
${AnsiColor.BRIGHT_RED}Spring Boot: ${spring-boot.formatted-version}
3.6 git 地址
spring-boot/spring-boot-05-basis/spring-boot-banner
4.测试
启动 SpringBootBannerApplication.main 方法,打印出 banner.txt 中内容
5.源码分析
5.1 banner 如何打印的?
banner 是如何打印的呢?
在 spring boot 项目启动时,调用 run 方法,最终会调用到 printBanner 方法
public ConfigurableApplicationContext run(String... args) {
// ...
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
// 打印 banner
Banner printedBanner = printBanner(environment);
// ...
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
//...
return context;
}
它的实现如下
private Banner printBanner(ConfigurableEnvironment environment) {
// 如果关闭 banner,直接返回
if (this.bannerMode == Banner.Mode.OFF) {
return null;
}
// 默认 resourceLoader=null,使用 DefaultResourceLoader
ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
: new DefaultResourceLoader(getClassLoader());
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
// bannerMode 有3中取值,OFF、CONSOLE、LOG,这里默认为 CONSOLE
if (this.bannerMode == Mode.LOG) {
return bannerPrinter.print(environment, this.mainApplicationClass, logger);
}
// 打印 banner
return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}
bannerPrinter.print
Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
// 获取 banner,先获获取图片类型,再获取文本类型,都没有则答应 Spring Boot
Banner banner = getBanner(environment);
// 如果有多种类型,循环打印;按照添加顺序,先图片再文本
banner.printBanner(environment, sourceClass, out);
return new PrintedBanner(banner, sourceClass);
}
banner.printBanner
@Override
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
for (Banner banner : this.banners) {
banner.printBanner(environment, sourceClass, out);
}
}
这里看下文本打印,ResourceBanner.printBanner
@Override
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
try {
// 获取编码格式
String banner = StreamUtils.copyToString(this.resource.getInputStream(),
environment.getProperty("spring.banner.charset", Charset.class, StandardCharsets.UTF_8));
// 处理 banner 文件中属性值
for (PropertyResolver resolver : getPropertyResolvers(environment, sourceClass)) {
banner = resolver.resolvePlaceholders(banner);
}
// 使用 java bio 进行打印
out.println(banner);
}
catch (Exception ex) {
logger.warn(
"Banner not printable: " + this.resource + " (" + ex.getClass() + ": '" + ex.getMessage() + "')",
ex);
}
}