教你怎麼用Springboot自定義Banner圖案

一、前言

我們在啟動 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字符和圖案,推薦網址如下:

  • 定制化 ASCII 字符:http://network-science.de/ascii/
  • 定制化 ASCII 圖片:https://www.degraeve.com/img2txt.php

到此這篇關於教你怎麼用Springboot自定義Banner圖案的文章就介紹到這瞭,更多相關Springboot自定義Banner圖案內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: