Document

java Spring Boot banner详解

Spring Boot 3.x系列文章

Spring Boot 2.7.8 中文参考指南(一)Spring Boot 2.7.8 中文参考指南(二)-WebSpring Boot 源码阅读初始化环境搭建Spring Boot 框架整体启动流程详解Spring Boot 系统初始化器详解Spring Boot 监听器详解Spring Boot banner详解

自定义banner

Spring Boot 默认打印的banner是这样的,Java工程师看都看腻了。

一般的公司如果有自己脚手架,都会选择自定义banner,放一个公司Logo或者框架别名。

简易版banner

首先生成一个自己的banner,比如我生成的

生成的网站很多,可以用"banner 生成器"自行搜索

把生成的内容copy到txt中,命名为"banner.txt"(UTF-8),然后放到resources下。 启动Spring Boot 即可看到效果。

自定义banner路径

上述的banner.txt 只能放在resources根目录下,不能在resources子目录或其他的目录,使用spring.banner.location指定该文件的路径,如果该文件不是UTF-8编码,使用spring.banner.charset指定文件编码,比如我将文件放到resources的子目录static中。

自定义banner 样式

光一个Logo也还是太单调,如果能再打印个Spring Boot 版本、应用程序版本就更好了,Spring Boot 都给我们提供了相关变量,可以在banner.txt中使用。

${application.version} 应用程序版本${application.formatted-version} 格式化的应用程序版本,前缀是v${spring-boot.version} Spring Boot框架版本${spring-boot.formatted-version} 格式化的Spring Boot框架版本,前缀是v${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME}) 给文字加颜色,加背景,加样式,NAME的值可以在这里获取ansi${application.title} 应用程序的标题

如图我给banner 加上了颜色,加上了版本

配置如下:

${AnsiColor.GREEN}

/$$$$$$ /$$$$$$ /$$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$$ /$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$ /$$

/$$__ $$ /$$__ $$| $$__ $$| $$$ | $$ |_ $$_/|__ $$__//$$__ $$ /$$__ $$| $$ /$$//$$__ $$ /$$__ $$| $$ /$$/

| $$ \__/| $$ \__/| $$ \ $$| $$$$| $$ | $$ | $$ | $$ \__/| $$ \ $$ \ $$ /$$/| $$ \__/| $$ \ $$ \ $$ /$$/

| $$ | $$$$$$ | $$ | $$| $$ $$ $$ /$$$$$$| $$ | $$ | $$$$$$ | $$$$$$$$ \ $$$$/ | $$$$$$ | $$$$$$$$ \ $$$$/

| $$ \____ $$| $$ | $$| $$ $$$$|______/| $$ | $$ \____ $$| $$__ $$ \ $$/ \____ $$| $$__ $$ \ $$/

| $$ $$ /$$ \ $$| $$ | $$| $$\ $$$ | $$ | $$ /$$ \ $$| $$ | $$ | $$ /$$ \ $$| $$ | $$ | $$

| $$$$$$/| $$$$$$/| $$$$$$$/| $$ \ $$ /$$$$$$ | $$ | $$$$$$/| $$ | $$ | $$ | $$$$$$/| $$ | $$ | $$

\______/ \______/ |_______/ |__/ \__/ |______/ |__/ \______/ |__/ |__/ |__/ \______/ |__/ |__/ |__/

${AnsiColor.DEFAULT}

::Spring Boot Version: ${AnsiColor.RED}${spring-boot.formatted-version}${AnsiColor.DEFAULT}

::Application Version: ${AnsiColor.RED}${application.formatted-version}${AnsiColor.DEFAULT}

如果颜色不起作用,那就是需要开启一下:spring.output.ansi.enabled=always${AnsiColor.DEFAULT} 是将颜色重置,防止前面的颜色影响下面的${application.formatted-version} 、 ${application.version}、 ${application.title} 要使用jar包启动才会打印banner.txt 中可以配置环境变量environment中的任何键值

使用图片做banner

在Spring Boot 3.x版本中已经不被支持

编码方式定义banner

自定义一个CustomBanner类,实现Banner接口,如:

import org.springframework.boot.Banner;

import org.springframework.core.env.Environment;

import java.io.PrintStream;

public class CustomBanner implements Banner {

public static final String BANNER = " /$$$$$$ /$$$$$$ /$$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$$ /$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$ /$$\n" +

" /$$__ $$ /$$__ $$| $$__ $$| $$$ | $$ |_ $$_/|__ $$__//$$__ $$ /$$__ $$| $$ /$$//$$__ $$ /$$__ $$| $$ /$$/\n" +

"| $$ \\__/| $$ \\__/| $$ \\ $$| $$$$| $$ | $$ | $$ | $$ \\__/| $$ \\ $$ \\ $$ /$$/| $$ \\__/| $$ \\ $$ \\ $$ /$$/ \n" +

"| $$ | $$$$$$ | $$ | $$| $$ $$ $$ /$$$$$$| $$ | $$ | $$$$$$ | $$$$$$$$ \\ $$$$/ | $$$$$$ | $$$$$$$$ \\ $$$$/ \n" +

"| $$ \\____ $$| $$ | $$| $$ $$$$|______/| $$ | $$ \\____ $$| $$__ $$ \\ $$/ \\____ $$| $$__ $$ \\ $$/ \n" +

"| $$ $$ /$$ \\ $$| $$ | $$| $$\\ $$$ | $$ | $$ /$$ \\ $$| $$ | $$ | $$ /$$ \\ $$| $$ | $$ | $$ \n" +

"| $$$$$$/| $$$$$$/| $$$$$$$/| $$ \\ $$ /$$$$$$ | $$ | $$$$$$/| $$ | $$ | $$ | $$$$$$/| $$ | $$ | $$ \n" +

" \\______/ \\______/ |_______/ |__/ \\__/ |______/ |__/ \\______/ |__/ |__/ |__/ \\______/ |__/ |__/ |__/ \n";

@Override

public void printBanner(Environment environment, Class sourceClass, PrintStream printStream) {

printStream.println(BANNER);

}

}

SpringApplication 中配置banner

SpringApplication springApplication = new SpringApplication(SpringBootDemoApplication.class);

springApplication.setBanner(new CustomBanner());

如果在类路径中存在banner.txt 在会优先使用banner.txt

禁用banner

Spring Boot 提供了spring.main.banner-mode 配置,OFF-关闭banner打印,CONSOLE-使用System.out打印banner,log文件不会记录,LOG-打印到log文件

另外同样可以用springApplication.setBannerMode(Banner.Mode.OFF);方式设置banner

加载打印原理

在之前的《Spring Boot 框架整体启动流程详解》中,我们看到有一步是

//打印banner

Banner printedBanner = printBanner(environment);

这一步就是加载打印banner的核心。

private Banner printBanner(ConfigurableEnvironment environment) {

//如果bannerMode是关闭的,就会不打印banner

if (this.bannerMode == Banner.Mode.OFF) {

return null;

}

//获取资源加载器,如果当前没有就使用默认的资源加载器

ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader

: new DefaultResourceLoader(null);

//创建一个SpringBoot应用程序的banner打印类,如果通过setBanner设置,this.banner会有值

SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);

//如果bannerMode 是打印到log文件

if (this.bannerMode == Mode.LOG) {

return bannerPrinter.print(environment, this.mainApplicationClass, logger);

}

//默认打印到控制台

return bannerPrinter.print(environment, this.mainApplicationClass, System.out);

}

先看下如何打印到log文件:

Banner print(Environment environment, Class sourceClass, Log logger) {

//获取Banner对象

Banner banner = getBanner(environment);

try {

//使用log 的info 级别打印

logger.info(createStringFromBanner(banner, environment, sourceClass));

}

catch (UnsupportedEncodingException ex) {

logger.warn("Failed to create String for banner", ex);

}

//创建一个打印banner的装饰器bean,允许后期再次使用

return new PrintedBanner(banner, sourceClass);

}

如何获取的Banner对象:

private Banner getBanner(Environment environment) {

//获取txt文本banner

Banner textBanner = getTextBanner(environment);

if (textBanner != null) {

return textBanner;

}

//fallbackBanner 为前期通过setBanner设置的自定义banner

//可见如果两者同时设置,优先使用的txt文本banner

if (this.fallbackBanner != null) {

return this.fallbackBanner;

}

//都没有,返回一个默认的SpringBootBanner

return DEFAULT_BANNER;

}

如果获取txt文本banner:

private Banner getTextBanner(Environment environment) {

//从环境变量中获取spring.banner.location指定的banner地址,如果没有,使用banner.txt

String location = environment.getProperty(BANNER_LOCATION_PROPERTY, DEFAULT_BANNER_LOCATION);

//获取指定的资源对象

Resource resource = this.resourceLoader.getResource(location);

try {

//资源存在,并且资源路径中不包含liquibase-core

if (resource.exists() && !resource.getURL().toExternalForm().contains("liquibase-core")) {

//创建一个从源打印的banner对象,实现了Banner接口

return new ResourceBanner(resource);

}

}

catch (IOException ex) {

// Ignore

}

return null;

}

获取到文本banner的ResourceBanner资源对象后,回到print(Environment environment, Class sourceClass, Log logger) 这个方法中,接下来就是要把获取到banner对象打印出来,createStringFromBanner将获取到banner对象,调用其中的printBanner方法,把输出流转为UTF-8的字符串输出到log文件中。

private String createStringFromBanner(Banner banner, Environment environment, Class mainApplicationClass)

throws UnsupportedEncodingException {

ByteArrayOutputStream baos = new ByteArrayOutputStream();

banner.printBanner(environment, mainApplicationClass, new PrintStream(baos));

String charset = environment.getProperty("spring.banner.charset", "UTF-8");

return baos.toString(charset);

}

ResourceBanner的printBanner方法:

public void printBanner(Environment environment, Class sourceClass, PrintStream out) {

try {

//从流读取banner.txt 字符串,使用spring.banner.charset编码,或者UTF-8

String banner = StreamUtils.copyToString(this.resource.getInputStream(),

environment.getProperty("spring.banner.charset", Charset.class, StandardCharsets.UTF_8));

//获取用于解析占位符的所有属性源

for (PropertyResolver resolver : getPropertyResolvers(environment, sourceClass)) {

//解析banner,使用PropertyPlaceholderHelper工具类解析

banner = resolver.resolvePlaceholders(banner);

}

//输出到流中

out.println(banner);

}

catch (Exception ex) {

logger.warn(LogMessage.format("Banner not printable: %s (%s: '%s')", this.resource, ex.getClass(),

ex.getMessage()), ex);

}

}

bannerPrinter.print(environment, this.mainApplicationClass, System.out); 打印到控制台的逻辑也是一样的,只是直接输出到控制台

Banner print(Environment environment, Class sourceClass, PrintStream out) {

Banner banner = getBanner(environment);

banner.printBanner(environment, sourceClass, out);

return new PrintedBanner(banner, sourceClass);

}

总结

通过图来总结一下整个流程

作者其他要推荐的文章,欢迎来学习: Prometheus 系列文章

Prometheus 的介绍和安装直观感受PromQL及其数据类型PromQL之选择器和运算符PromQL之函数Prometheus 告警机制介绍及命令解读Prometheus 告警模块配置深度解析Prometheus 配置身份认证Prometheus 动态拉取监控服务Prometheus 监控云Mysql和自建Mysql

Grafana 系列文章,版本:OOS v9.3.1

Grafana 的介绍和安装Grafana监控大屏配置参数介绍(一)Grafana监控大屏配置参数介绍(二)Grafana监控大屏可视化图表Grafana 查询数据和转换数据Grafana 告警模块介绍Grafana 告警接入飞书通知

Spring Boot Admin 系列

Spring Boot Admin 参考指南SpringBoot Admin服务离线、不显示健康信息的问题Spring Boot Admin2 @EnableAdminServer的加载Spring Boot Admin2 AdminServerAutoConfiguration详解Spring Boot Admin2 实例状态监控详解Spring Boot Admin2 自定义JVM监控通知Spring Boot Admin2 自定义异常监控Spring Boot Admin 监控指标接入Grafana可视化

 

posted @ 2023-07-25 15:44  从未被超越  阅读(1207)  评论(0)    收藏  举报