一、什么是Banner
当我们启动一个SpringBoot应用之后,经常会在控制台看到如下打印
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)
该输出就是Banner,看起来像是一个项目的标志一样。
二、如何自定义Banner
如果想让自己项目的banner打印自己想要的图案:例如公司LOGO等,应该要怎么办呢?
很简单,只需要在SpringBoot工程的 /src/main/resources 目录下创建一个名为 banner.txt 的文件即可,这样,容器在启动时就会将此文件中的文本打印在控制台啦。
那么怎么来绘制一些图案呢?现在有很多现成的网站支持设计banner,可以参考
1.http://patorjk.com/software/taag
输入文本进行转化
2.http://www.network-science.de/ascii/
输入文本进行转化
3.http://www.degraeve.com/img2txt.php
可以将一个图片转为文字格式图画
三、源码剖析
那么SpringBoot是如何实现的呢?
在SpringApplication的run方法中,有一行Banner printedBanner = printBanner(environment);在该方法中进行banner的获取和打印。
SpringApplication.printBanner
private Banner printBanner(ConfigurableEnvironment environment) {
检查打印Banner的开关是否启
if (this.bannerMode == Banner.Mode.OFF) {
return null;
}
ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
: new DefaultResourceLoader(getClassLoader());
//准备printer
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.Mode有三种:
OFF 不进行任何形式的Banner输出
CONSOLE 在控制台进行Banner的打印
LOG 打印Banner到日志文件中
SpringApplication中默认Banner.Mode类型为CONSOLE。
ResourceLoader是spring提供用于获取classpath下或者resource目录下资源的策略接口。在拿到ResourceLoader之后将其封装为SpringApplicationBannerPrinter。之后调用其print方法。
SpringApplicationBannerPrinter.print
public Banner print(Environment environment, Class> sourceClass, PrintStream out) {
//获取banner
Banner banner = getBanner(environment);
//打印banner
banner.printBanner(environment, sourceClass, out);
return new PrintedBanner(banner, sourceClass);
}
SpringApplicationBannerPrinter.getBanner
private Banner getBanner(Environment environment) {
Banners banners = new Banners();
banners.addIfNotNull(getImageBanner(environment));
banners.addIfNotNull(getTextBanner(environment));
if (banners.hasAtLeastOneBanner()) {
return banners;
}
if (this.fallbackBanner != null) {
return this.fallbackBanner;
}
return DEFAULT_BANNER;
}
从getBanner代码中看,不仅支持txt形式的banner,也支持图片资源banner。查看getImageBanner(environment)方法实现,可知SpringBoot将从spring.banner.image.location属性中获取图片路径,支持gif,jpg,png,然后封装为ImageBanerr。其中Banners实质是维护了一个banner列表。在真正打印的时候进行遍历打印。
SpringApplicationBannerPrinter.printBanner
public void printBanner(Environment environment, Class> sourceClass, PrintStream out) {
for (Banner banner : this.banners) {
banner.printBanner(environment, sourceClass, out);
}
}
所有springboot同时也支持多个banner的打印。
四、源码总结
从源码中我们可以知道更多有关banner的支持,下面将列述
默认自定义banner,只需要在resource目录下放置一个banner.txt文件即可,如果不想命名为banner.txt,则可以指定属性spring.banner.location为自定义文件名即可
支持图片资源banner。指定属性spring.banner.image.location为图片资源路径
SpringBoot支持同时配置txt形式和图片形式banner,并同时打印。