SpringBoot開發 - 如何定製自己的Banner?還能用圖片? 我們在啟動Spring Boot程式時,有SpringBoot的Banner信息,那麼如何自定義成自己項目的信息呢? @pdai SpringBoot開發 - 如何定製自己的Banner?還能用圖片? 什麼是Banner 如何更 ...
SpringBoot開發 - 如何定製自己的Banner?還能用圖片?
我們在啟動Spring Boot程式時,有SpringBoot的Banner信息,那麼如何自定義成自己項目的信息呢? @pdai
什麼是Banner
我們在啟動Spring Boot程式時,有如下Banner信息:
那麼如何自定義成自己項目的名稱呢?
如何更改Banner
更改Banner有如下幾種方式:
- banner.txt配置(最常用)
在application.yml中添加配置
spring:
banner:
charset: UTF-8
location: classpath:banner.txt
在resource下創建banner.txt,內容自定義:
----welcome----
https://pdai.tech
---------------
修改後,重啟的app的效果
- SpringApplication啟動時設置參數
SpringApplication application = new SpringApplication(App.class);
/**
* Banner.Mode.OFF:關閉;
* Banner.Mode.CONSOLE:控制台輸出,預設方式;
* Banner.Mode.LOG:日誌輸出方式;
*/
application.setBannerMode(Banner.Mode.OFF); // here
application.run(args);
SpringApplication還可以設置自定義的Banner的介面類
文字Banner的設計
如何設計上面的文字呢?
一些設計Banner的網站
可以通過這個網站進行設計:patorjk Banner
比如:
我們修改banner.txt, 運行的效果如下
IDEA中Banner的插件
IDEA中也有插件,不過沒有預覽功能
其它工具
http://www.network-science.de/ascii/
http://www.degraeve.com/img2txt.php
http://www.bootschool.net/ascii
Banner中其它配置信息
除了文件信息,還有哪些信息可以配置呢?比如Spring預設還帶有SpringBoot當前的版本號信息。
在banner.txt中,還可以進行一些設置:
# springboot的版本號
${spring-boot.version}
# springboot的版本號前面加v後上括弧
${spring-boot.formatted-version}
# MANIFEST.MF文件中的版本號
${application.version}
# MANIFEST.MF文件的版本號前面加v後上括弧
${application.formatted-version}
# MANIFEST.MF文件中的程式名稱
${application.title}
# ANSI樣色/樣式等
${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME})
簡單的測試如下(註意必須打包出Jar, 才會生成resources/META-INF/MANIFEST.MF):
動畫Banner的設計
那我能不能設置動態的Banner呢?比如一個圖片?
SpringBoot2是支持圖片形式的Banner,
spring:
main:
banner-mode: console
show-banner: true
banner:
charset: UTF-8
image:
margin: 0
height: 10
invert: false
location: classpath:pdai.png
效果如下(需要選擇合適的照片,不然效果不好, 所以這種方式很少使用),
註意: 格式不能太大,不然會報錯
org.springframework.boot.ImageBanner : Image banner not printable: class path resource [banner.gif] (class java.lang.ArrayIndexOutOfBoundsException: '4096')
進一步思考
圖片Banner是如何起作用的?
發現 Springboot 可以把圖片轉換成 ASCII 圖案,那麼它是怎麼做的呢?以此為例,我們看下Spring 的Banner是如何生成的呢?
- 獲取Banner
- 優先順序是環境變數中的Image優先,格式在IMAGE_EXTENSION中
- 然後才是banner.txt
- 沒有的話就用SpringBootBanner
- 如果是圖片
- 獲取圖片Banner(屬性配置等)
- 轉換成ascii
獲取banner
class SpringApplicationBannerPrinter {
static final String BANNER_LOCATION_PROPERTY = "spring.banner.location";
static final String BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location";
static final String DEFAULT_BANNER_LOCATION = "banner.txt";
static final String[] IMAGE_EXTENSION = new String[]{"gif", "jpg", "png"};
private static final Banner DEFAULT_BANNER = new SpringBootBanner(); // 預設的Spring Banner
private final ResourceLoader resourceLoader;
private final Banner fallbackBanner;
// 獲取Banner,優先順序是環境變數中的Image優先,格式在IMAGE_EXTENSION中,然後才是banner.txt
private Banner getBanner(Environment environment) {
SpringApplicationBannerPrinter.Banners banners = new SpringApplicationBannerPrinter.Banners();
banners.addIfNotNull(this.getImageBanner(environment));
banners.addIfNotNull(this.getTextBanner(environment));
if (banners.hasAtLeastOneBanner()) {
return banners;
} else {
return this.fallbackBanner != null ? this.fallbackBanner : DEFAULT_BANNER;
}
}
獲取圖片Banner
private Banner getImageBanner(Environment environment) {
String location = environment.getProperty("spring.banner.image.location");
if (StringUtils.hasLength(location)) {
Resource resource = this.resourceLoader.getResource(location);
return resource.exists() ? new ImageBanner(resource) : null;
} else {
String[] var3 = IMAGE_EXTENSION;
int var4 = var3.length;
for(int var5 = 0; var5 < var4; ++var5) {
String ext = var3[var5];
Resource resource = this.resourceLoader.getResource("banner." + ext);
if (resource.exists()) {
return new ImageBanner(resource);
}
}
return null;
}
}
獲取圖片的配置等
private void printBanner(Environment environment, PrintStream out) throws IOException {
int width = (Integer)this.getProperty(environment, "width", Integer.class, 76);
int height = (Integer)this.getProperty(environment, "height", Integer.class, 0);
int margin = (Integer)this.getProperty(environment, "margin", Integer.class, 2);
boolean invert = (Boolean)this.getProperty(environment, "invert", Boolean.class, false); // 圖片的屬性
BitDepth bitDepth = this.getBitDepthProperty(environment);
ImageBanner.PixelMode pixelMode = this.getPixelModeProperty(environment);
ImageBanner.Frame[] frames = this.readFrames(width, height); // 讀取圖片的幀
for(int i = 0; i < frames.length; ++i) {
if (i > 0) {
this.resetCursor(frames[i - 1].getImage(), out);
}
this.printBanner(frames[i].getImage(), margin, invert, bitDepth, pixelMode, out);
this.sleep(frames[i].getDelayTime());
}
}
轉換成ascii
private void printBanner(BufferedImage image, int margin, boolean invert, BitDepth bitDepth, ImageBanner.PixelMode pixelMode, PrintStream out) {
AnsiElement background = invert ? AnsiBackground.BLACK : AnsiBackground.DEFAULT;
out.print(AnsiOutput.encode(AnsiColor.DEFAULT));
out.print(AnsiOutput.encode(background));
out.println();
out.println();
AnsiElement lastColor = AnsiColor.DEFAULT;
AnsiColors colors = new AnsiColors(bitDepth);
for(int y = 0; y < image.getHeight(); ++y) {
int x;
for(x = 0; x < margin; ++x) {
out.print(" ");
}
for(x = 0; x < image.getWidth(); ++x) {
Color color = new Color(image.getRGB(x, y), false);
AnsiElement ansiColor = colors.findClosest(color);
if (ansiColor != lastColor) {
out.print(AnsiOutput.encode(ansiColor));
lastColor = ansiColor;
}
out.print(this.getAsciiPixel(color, invert, pixelMode)); // // 像素點轉換成字元輸出
}
out.println();
}
out.print(AnsiOutput.encode(AnsiColor.DEFAULT));
out.print(AnsiOutput.encode(AnsiBackground.DEFAULT));
out.println();
}
示例源碼
https://github.com/realpdai/tech-pdai-spring-demos
更多內容
告別碎片化學習,無套路一站式體系化學習後端開發: Java 全棧知識體系(https://pdai.tech)
更多文章請參考 [Java 全棧知識體系](https://pdai.tech)