简析Spring Boot启动时控制台打印logo的实现原理

844 字
4 分钟
简析Spring Boot启动时控制台打印logo的实现原理

Spring Boot应用程序启动之后都会在输出的日志中打印具有独特表示的logo和版本信息。示例如下:

Terminal window
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.14)

那么它究竟是如何实现的呢?带着这种好奇和疑问,开始正文。

Spring Boot实现方案#

打印输出的核心关键工具类是SpringBootBanner。源码如下:

class SpringBootBanner implements Banner {
private static final String[] BANNER = { "", " . ____ _ __ _ _",
" /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\", "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\",
" \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )", " ' |____| .__|_| |_|_| |_\\__, | / / / /",
" =========|_|==============|___/=/_/_/_/" };
private static final String SPRING_BOOT = " :: Spring Boot :: ";
private static final int STRAP_LINE_SIZE = 42;
@Override
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
for (String line : BANNER) {
printStream.println(line);
}
String version = SpringBootVersion.getVersion();
version = (version != null) ? " (v" + version + ")" : "";
StringBuilder padding = new StringBuilder();
while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) {
padding.append(" ");
}
printStream.println(AnsiOutput.toString(AnsiColor.GREEN, SPRING_BOOT, AnsiColor.DEFAULT, padding.toString(),
AnsiStyle.FAINT, version));
printStream.println();
}
}

自定义Spring Boot Banner#

Spring Boot提供了 spring.banner.location 支持玩家自定义banner,支持图片格式(banner.gif, banner.jpg, banner.png),也支持文本格式(banner.txt)。

spring:
banner:
charset: utf-8
location: classpath:banner.txt # banner文本文件路径
image: # banner图片文件路径
location: classpath:banner.png
width: 80
margin: 1
invert: false
main:
banner-mode: "off"

可以通过Banner生成器 在线生成想要的字符文字效果。

Banner中提供了几个变量占位符,用来丰富打印的数据内容。列表如下:

变量描述
${application.version}应用程序的版本号
${application.formatted-version}
${spring-boot.version}Spring Boot版本号
${spring-boot.formatted-version}
Ansi.NAME(or{Ansi.NAME} (or {AnsiColor.NAME}, AnsiBackground.NAME,{AnsiBackground.NAME}, {AnsiStyle.NAME})ANSI设置
${application.title}应用程序标题

Banner有一个输出模式的控制开关,内置三种模式 OFF(关闭), CONSOLE(仅控制台), LOG(追加日志)

public interface Banner {
/**
* Print the banner to the specified print stream.
* @param environment the spring environment
* @param sourceClass the source class for the application
* @param out the output print stream
*/
void printBanner(Environment environment, Class<?> sourceClass, PrintStream out);
/**
* An enumeration of possible values for configuring the Banner.
*/
enum Mode {
/**
* Disable printing of the banner.
*/
OFF,
/**
* Print the banner to System.out.
*/
CONSOLE,
/**
* Print the banner to the log file.
*/
LOG
}
}
// 通过SpringApplication设置定制的Banner实例
// SpringApplication.setBanner(…​)

控制Banner输出的核心业务方法如下:

private Banner printBanner(ConfigurableEnvironment environment) {
if (this.bannerMode == Banner.Mode.OFF) {
return null;
}
ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
: new DefaultResourceLoader(null);
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
if (this.bannerMode == Mode.LOG) {
return bannerPrinter.print(environment, this.mainApplicationClass, logger);
}
return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}

定制个人项目的专属Banner#

了解Spring Boot的实现方案后,我就可以在项目中实现自定义的Banner。

public enum StructBanner {
INSTANCE;
private static final Logger LOGGER = LoggerFactory.getLogger(StructBanner.class);
/**
* font: doom
* content: "*Struct>>>"
*/
private static final String[] BANNER = {
" _ _____ _ _ ______ ",
" /\\| |/\\/ ___| | | | \\ \\ \\ \\ ",
" \\ ` ' /\\ `--.| |_ _ __ _ _ ___| |_ \\ \\ \\ \\ ",
"|_ _|`--. \\ __| '__| | | |/ __| __| > > > >",
" / , . \\/\\__/ / |_| | | |_| | (__| |_ / / / / ",
" \\/|_|\\/\\____/ \\__|_| \\__,_|\\___|\\__/_/_/_/ "
};
private static final String STRUCT_STORE_SERVICE = " :: Struct Store Service :: ";
private static final String VERSION = loadVersionProperties();
/**
* Print struct store service banner.
*/
public void print() {
PrintStream ps = System.out;
for (String line : BANNER) {
ps.println(line);
}
ps.println(STRUCT_STORE_SERVICE + " (" + getVersion() + ")");
}
/**
* Get struct library version.
*
* @return Struct library version.
*/
public String getVersion() {
return VERSION;
}
static String loadVersionProperties() {
Properties prop = new Properties();
try (InputStream in = StructBanner.class.getResourceAsStream("/META-INF/maven/org.structutil/struct-spring/pom.properties")) {
prop.load(in);
return prop.getProperty("version", "Unknown");
} catch (Throwable e) {
LOGGER.error("");
}
return "Unknown";
}
}

打印输出结果:

Terminal window
_ _____ _ _ ______
/\| |/\/ ___| | | | \ \ \ \
\ ` ' /\ `--.| |_ _ __ _ _ ___| |_ \ \ \ \
|_ _|`--. \ __| '__| | | |/ __| __| > > > >
/ , . \/\__/ / |_| | | |_| | (__| |_ / / / /
\/|_|\/\____/ \__|_| \__,_|\___|\__/_/_/_/
:: Struct Store Service :: (Unknown)

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
简析Spring Boot启动时控制台打印logo的实现原理
https://tinyzzh.github.io/posts/2023-02-10-spring_boot_banner/
作者
TinyZ Zzh
发布于
2023-02-10
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
TinyZ Zzh
专注于高并发服务器、网络游戏相关(Java、PHP、Unity3D、Unreal Engine等)技术,热爱游戏事业, 正在努力实现自我价值当中。
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
211
分类
38
标签
200
总字数
337,853
运行时长
0
最后活动
0 天前

文章目录