我是陈皮,一个在互联网 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 信息。主要是 ImageBannerResourceBannerSpringBootBanner 这三个实现类。

  1. 项目启动时,会判断是否某些条件成立(项目中是否存在 banner 文件),成立则创建 ImageBannerResourceBanner 类对象,并且使用它们来打印 banner。
  2. 如果不成立检查是否存在我们自定义的 Banner 实现类 fallbackBanner,如果存在则使用它来打印 banner 图案。
  3. 否则,则使用默认的 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;
}

ImageBanner

org.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

org.springframework.boot.ResourceBanner 类是专门加载和打印字符 banner 的。它检查配置文件 application.proeprties 是否有配置的 spring.banner.location 变量的值,这个值可用来指定要加载的文件,如果存在则构建 ResourceBanner 对象。如果没有配置变量,则还会检查资源路径下是否存在 banner.txt 文件,如果存在也会构建 ResourceBanner 对象。

class SpringApplicationBannerPrinter {

	static final String BANNER_LOCATION_PROPERTY = "spring.banner.location";

	static final String DEFAULT_BANNER_LOCATION = "banner.txt";

	// 获取 ResourceBanner 对象
private Banner getTextBanner(Environment environment) {
String location = environment.getProperty(BANNER_LOCATION_PROPERTY, DEFAULT_BANNER_LOCATION);
Resource resource = this.resourceLoader.getResource(location);
if (resource.exists()) {
return new ResourceBanner(resource);
}
return null;
}
}

如果想要自定义 banner,我们一般在项目的 resources 资源目录下创建 banner.txt 文件,然后在里面填入我们想要的打印的文字内容即可。例如我在 banner.txt 文件中填充了 Chen Pi 内容,然后启动项目。

SpringBootBanner

如果项目没有设置以上两种自定义的 banner(ImageBanner 和 ResourceBanner),则默认情况下,会使用 SpringBootBanner 实现类打印 banner ,也就是我们启动 Springboot 项目时在控制台看到的打印 Spring 图案。源码如下:

package org.springframework.boot;

import java.io.PrintStream;

import org.springframework.boot.ansi.AnsiColor;
import org.springframework.boot.ansi.AnsiOutput;
import org.springframework.boot.ansi.AnsiStyle;
import org.springframework.core.env.Environment; /**
* Default Banner implementation which writes the 'Spring' banner.
*/
class SpringBootBanner implements Banner {
// 这个就是我们启动 Springboot 项目时在控制台看到的图案
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();
} }

实现 Banner 类

前面说我们可以实现 Banner 类,重写打印方法,实现自定义 banner 打印功能。

package com.chenpi;

import java.io.PrintStream;
import org.springframework.boot.Banner;
import org.springframework.core.env.Environment; /**
* @Description 自定义 Banner 实现类
* @Author Mr.nobody
* @Date 2021/6/4
* @Version 1.0
*/
public class MyBanner implements Banner { @Override
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) { String banner = " .__ .__ \n"
+ " ____ | |__ ____ ____ ______ |__|\n"
+ "_/ ___\\| | \\_/ __ \\ / \\ \\____ \\| |\n"
+ "\\ \\___| Y \\ ___/| | \\ | |_> > |\n"
+ " \\___ >___| /\\___ >___| / | __/|__|\n"
+ " \\/ \\/ \\/ \\/ |__| "; out.println(banner);
}
}

创建自定义的 Banner 实现类对象,设置到 SpringApplication 类对象的 banner 属性,最终这个属性的值会会被赋值到 SpringApplicationBannerPrinter 对象的 fallbackBanner 属性中,感兴趣的可以启动 debug 跟踪下。

package com.chenpi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class SpringBootBannerApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(SpringBootBannerApplication.class);
// 设置自定义 Banner
springApplication.setBanner(new MyBanner());
// 启动 SpringBoot
springApplication.run(args);
}
}

Banner 样式控制

文章一开始的佛祖图形,你会发现是翠绿色的。其实 Springboot 支持我们修改 banner 的颜色,字体斜体,粗体等样式。SpringBoot 为我们提供了三个枚举类来设定这些样式。

  1. AnsiColor:设定字符的前景色;参考 org.springframework.boot.ansi.AnsiColor 枚举类。
  2. AnsiBackground:设定字符的背景色;参考 org.springframework.boot.ansi.AnsiBackground 枚举类。
  3. AnsiStyle:设定字符的加粗、斜体、下划线等等;参考 org.springframework.boot.ansi.AnsiStyle 枚举类。

而且,在 banner.txt 文件中还可以引用一些全局变量,例如:

  1. ${spring-boot.version}:Spring Boot 版本号;
  2. ${spring-boot.formatted-version}:格式化后的 Spring Boot 版本号信息。
  3. ${application.version}:MANIFEST.MF 文件中的版本号;
  4. ${application.formatted-version}:格式化后的 MANIFEST.MF 文件中的版本号信息;

不仅如此,还可以引用我们在配置文件 application.properties 中定义的变量,例如在配置文件中定义了如下变量:

application.auth=chenpi

定义的 banner.txt 文件内容如下:

${AnsiColor.BRIGHT_GREEN}
////////////////////////////////////////////////////////////////////
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
////////////////////////////////////////////////////////////////////
${AnsiColor.BRIGHT_CYAN}
Application Version: ${application.version}${application.formatted-version}
Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version} By -- ${application.auth}

启动项目,会在控制台打印的 banner 如下:

Banner 模式

在 Banner 接口中有定义一个枚举类,这个枚举定义了配置 Banner 的可能枚举值,如下:

@FunctionalInterface
public interface Banner { // 用于配置Banner的的枚举值
enum Mode {
// 关闭 banner 打印
OFF,
// 打印 banner 到 控制台
CONSOLE,
// 打印 banner 到日志文件
LOG
}
}

所以我们可以选择关闭 banner,banner 打印到控制台还是日志文件,如下:

package com.chenpi;

import org.springframework.boot.Banner.Mode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class SpringBootBannerApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(SpringBootBannerApplication.class);
// 关闭 banner
springApplication.setBannerMode(Mode.OFF);
// 启动 SpringBoot
springApplication.run(args);
}
}

也可以配置文件中设置此值,如下

spring.main.banner-mode=off

如果启动类跟配置文件中都配置了对banner开关的设置,配置文件中设置的banner开关会优先于启动类中设置的开关。

banner 图生成工具

可能有人会问佛祖的图案怎么编辑出来的,其实网上有很多工具可以根据我们输入的内容或者图片,个性化制作ASCII字符和图案,推荐网址如下:

Spring Boot - 自定义 Banner 图案的更多相关文章

  1. Spring Boot自定义Banner

    在2016年的最后一天,借用Spring Boot的Banner向各位程序猿同仁们问候一声:Happy New Year. 接下来我们就来介绍一下这个轻松愉快的自定义banner功能.实现的方式非常简 ...

  2. Spring Boot 自定义 Banner 教程

    我们在启动 SpringBoot 时,控制台会打印 SpringBoot Logo 以及版本信息.有的时候我们需要自己弄个有个性的文本图片.Spring Boot 为我们提供了自定义接口. . ___ ...

  3. Spring boot 自定义banner的在线制作

    目前工作不是很忙,利用闲暇的时间,在给自己不断地充电,提升自己的技术实力. 目前在做一个基于Spring Boot2.x+webmagic+quartz的爬虫项目[hotDog]https://git ...

  4. Spring boot 自定义banner

    Spring Boot启动的时候会在命令行生成一个banner,其实这个banner是可以自己修改的,本文将会将会讲解如何修改这个banner. 首先我们需要将banner保存到一个文件中,网上有很多 ...

  5. Spring Boot定制启动图案

    启动图案 Spring Boot在启动的时候会显示一个默认的Spring的图案,对应的类为SpringBootBanner. . ____ _ __ _ _ /\\ / ___'_ __ _ _(_) ...

  6. spring boot自定义线程池以及异步处理

    spring boot自定义线程池以及异步处理@Async:什么是线程池?线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使 ...

  7. Spring Boot自定义配置与加载

    Spring Boot自定义配置与加载 application.properties主要用来配置数据库连接.日志相关配置等.除了这些配置内容之外,还可以自定义一些配置项,如: my.config.ms ...

  8. Spring Boot 2.X(四):Spring Boot 自定义 Web MVC 配置

    0.准备 Spring Boot 不仅提供了相当简单使用的自动配置功能,而且开放了非常自由灵活的配置类.Spring MVC 为我们提供了 WebMvcConfigurationSupport 类和一 ...

  9. Spring Boot自定义Redis缓存配置,保存value格式JSON字符串

    Spring Boot自定义Redis缓存,保存格式JSON字符串 部分内容转自 https://blog.csdn.net/caojidasabi/article/details/83059642 ...

随机推荐

  1. Java代理简述

    1.什么是代理? 对类或对象(目标对象)进行增强功能,最终形成一个新的代理对象,(Spring Framework中)当应用调用该对象(目标对象)的方法时,实际调用的是代理对象增强后的方法,比如对功能 ...

  2. String a=new String("abc")创建了几个对象

    String str=new String("abc");   紧接着这段代码之后的往往是这个问题,那就是这行代码究竟创建了几个String对象呢? 相信大家对这道题并不陌生,答案 ...

  3. k8s service NodePort 方式向外发布

    k8s service NodePort 方式向外发布 k8s 无头service 方式向内发布 k8s service 服务发现 {ServiceName}.{Namespace}.svc.{Clu ...

  4. 【软件工程】《构建之法》 & Git+ & CI/CD

    <构建之法> & Git+ & CI/CD 个人阅读作业#2 项目 内容 本作业所属课程 2020春季软件工程(罗杰 任健) 本作业要求 个人阅读作业#2 我的课程目标 具 ...

  5. 01- web测试快速入门

    web测试与APP测试最非常重要的两个测试种类.web端指的就是在浏览器页面的测试. 你测试的软件通常是两种结构的,B/S架构与C/S架构. B/S架构:Browser/Server 浏览器与服务器模 ...

  6. SSDT表结构的深入学习

    SSDT表的知识目录: A.了解SSDT结构 B.由SSDT索引号获取当前函数地址        C.如何获取索引号 D.获取起源地址-判断SSDT是否被HOOK E.如何向内核地址写入自己代码 A. ...

  7. hdu5247找连续数(打表)

    题意(中问题直接粘题意吧)                                 找连续数 Problem Description 小度熊拿到了一个无序的数组,对于这个数组,小度熊想知道是否 ...

  8. POJ1719行列匹配

    题意:      给一个n*m的格子,每一列都有两个白色的,其余的全是黑色的,然后要选择m个格子,要求是每一列必须也只能选一个,而每一行至少选择一个,输出一种可行的方案没,输出的格式是输出m个数,表示 ...

  9. Day009 二维数组

    多维数组 多维数组是数组的嵌套(数组的元素是数组,数组的数组元素的元素是数组...),比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组. 二维数组 int a[][]=new int ...

  10. Mac SSH工具-Termius

    全平台,功能强大 SSH连接.SFTP连接.端口转发.多设备同步 官方网站