我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复【资料】,即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板。
前言我们在启动 Spring Boot 项目时,默认会在控制台打印 Spring logo 和版本等信息,如下:
这就是 Spring Boot 的 Banner 打印功能,其实我们可以自定义打印的 banner ,也可以禁用和启用打印 banner 功能。在真实项目中,我们一般不会去自定义 banner 图案,它其实就是项目启动时打印图案或者文字而已,没实际意义。推荐在自己个人项目玩玩这个彩蛋即可,顺便简单了解下它内部实现原理。
比如,自定义一个 banner 之后,项目启动控制台打印如下所示:
实现原理Spring Boot 有一个接口 org.springframework.boot.Banner 专门实现这个操作。要想自定义打印 banner ,只要自定义一个类实现这个接口,重写 printBanner 方法进行打印即可。Springboot 项目启动时,会创建我们的实现类对象,并调用对象的 printBanner 方法。
package org.springframework.boot; import java.io.PrintStream; import org.springframework.core.env.Environment; /** * Interface class for writing a banner programmatically. * 用于以编程方式编写 banner 的接口类 * @since 1.2.0 */ @FunctionalInterface public interface Banner { /** * Print the banner to the specified print stream. * 将 banner 打印到指定的打印流。 * @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); // 用于配置Banner的的枚举值 enum Mode { // 关闭 banner 打印 OFF, // 打印 banner 到 控制台 CONSOLE, // 打印 banner 到日志文件 LOG } } 默认 Banner 实现类Springboot 已经有几个自带的 Banner 实现类,Springboot 启动时会根据条件选择不同的 Banner 实现类进行打印 banner 信息。主要是 ImageBanner,ResourceBanner,SpringBootBanner 这三个实现类。
项目启动时,会判断是否某些条件成立(项目中是否存在 banner 文件),成立则创建 ImageBanner 和 ResourceBanner 类对象,并且使用它们来打印 banner。
如果不成立检查是否存在我们自定义的 Banner 实现类 fallbackBanner,如果存在则使用它来打印 banner 图案。
否则,则使用默认的 SpringBootBanner 实现类来打印 banner,也就是我们经常看到 Spring 图案。
// 获取可用的 Banner 实现类 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; } // SpringBootBanner 实现类 return DEFAULT_BANNER; } ImageBannerorg.springframework.boot.ImageBanner 类是专门加载和打印图片 banner 的。它检查配置文件 application.proeprties 是否有配置的 spring.banner.image.location 变量的值,这个值可用来指定要加载的图片,如果存在则构建 ImageBanner 对象。如果没有配置变量,则还会检查 Classpath 下是否存在以 banner 开头,以 .gif,.jpg,.png 结尾的图片文件,如果有也会构建 ImageBanner 对象。
class SpringApplicationBannerPrinter { static final String BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location"; static final String[] IMAGE_EXTENSION = { "gif", "jpg", "png" }; // 获取 ImageBanner 对象 private Banner getImageBanner(Environment environment) { // 加载 spring.banner.image.location 指定的文件,文件存在则构建 ImageBanner 对象 String location = environment.getProperty(BANNER_IMAGE_LOCATION_PROPERTY); if (StringUtils.hasLength(location)) { Resource resource = this.resourceLoader.getResource(location); return resource.exists() ? new ImageBanner(resource) : null; } // 查找 banner.gif,banner.jpg,banner.png 文件 for (String ext : IMAGE_EXTENSION) { Resource resource = this.resourceLoader.getResource("banner." + ext); if (resource.exists()) { return new ImageBanner(resource); } } return null; } } ResourceBanner