SpringBoot實戰分析(五)Banner(Logo)加載與配置

入口

SpringApplication的			
Banner printedBanner = printBanner(environment);

斷點跟蹤

1.判斷當前的Banner打印位置

private Banner printBanner(ConfigurableEnvironment environment) {
    //判斷banner是否關閉
    if (this.bannerMode == Banner.Mode.OFF) {
        return null;
    }
    ResourceLoader resourceLoader = (this.resourceLoader != null ? this.resourceLoader
            : new DefaultResourceLoader(getClassLoader()));
    SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(
            resourceLoader, this.banner);
   //打印到日誌文件中
    if (this.bannerMode == Mode.LOG) {
        return bannerPrinter.print(environment, this.mainApplicationClass, logger);
    }
    // 默認console 打印在控制檯
    return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}

Mode是個枚舉類包括三個值:


2.默認打印SpringBoot內置的Banner

直接看print方法,因爲是走的控制檯,所以直接上面的最後一個return返回。

public Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
    Banner banner = getBanner(environment);
    banner.printBanner(environment, sourceClass, out);
    return new PrintedBanner(banner, sourceClass);
}
這裏就是要準備加載配置的地方了,可以在application中配置,也可以直接在resources下面寫Banner.txt或者Banner.jpg/png/gif 這幾種文件,這裏先加載默認配置。先加載Image,然後加載文件Text文件。
private Banner getBanner(Environment environment) {
    Banners banners = new Banners();
   //獲取圖片Banner
    banners.addIfNotNull(getImageBanner(environment));
   //獲取文本Banner
    banners.addIfNotNull(getTextBanner(environment));
    if (banners.hasAtLeastOneBanner()) {
        return banners;
    }
    if (this.fallbackBanner != null) {
        return this.fallbackBanner;
    }
    return DEFAULT_BANNER;
}

加載圖片Banner,這有一個靜態的屬性值

static final String BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location"; 這個值對應的是Application.yml中的配置項。這麼寫就會加載tim.jpg的圖片內容當作Banner。會通過下面的for循環得到是那種圖片。然後處理。


如果不做配置,默認情況下這個方法會return一個null返回。

private Banner getImageBanner(Environment environment) {
    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);
    }
   // IMAGE_EXTENSION 這個常量值:{ "gif", "jpg", "png" }
    for (String ext : IMAGE_EXTENSION) {
        Resource resource = this.resourceLoader.getResource("banner." + ext);
        if (resource.exists()) {
            return new ImageBanner(resource);
        }
    }
    return null;
}

這個方法是去加載文本的Banner,這個地方的兩個常量是,

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

static final String DEFAULT_BANNER_LOCATION = "banner.txt";

還是對應的配置文件中的屬性和classpath中的banner.txt文件。

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;
}

因爲是默認加載配置,所以getBanner()最後會返回

DEFAULT_BANNER = new SpringBootBanner()

看一下SpringBootBanner的構成。這個位置就是SpringBoot默認加載的Banner。

默認Banner的輸出會調用SpringBootBanner中的這個方法。

@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();
}
循環按照line去讀取定義的banner字符串。然後用StringBuilder拼接字符,調用printStream.println()進行打印。

默認打印值:



3.打印自定義Banner.txt文件內容

文件位置和文件內容(bug game over)


這個自定義的文件只是影響了下面這個方法,因爲他不在是null的,resource包含了自定義的Banner.txt。但是加載圖片的那個還是null。

banners.addIfNotNull(getTextBanner(environment));


getBanner(Environment environment)這個方法就不會返回默認值,而是走if判斷。

if (banners.hasAtLeastOneBanner()) {

return banners;

}

這次調用print的時候是調用SpringApplicationBannerPrinter中的

@Override
public void printBanner(Environment environment, Class<?> sourceClass,
        PrintStream out) {
    for (Banner banner : this.banners) {
        banner.printBanner(environment, sourceClass, out);
    }
}

這方法會調用ResourceBanner這個類中的printBanner,


控制檯打印:


4.打印自定義圖片的Banner

調用和加載Banner.txt差不多。只是在打印方法上調用的不一樣。

調用這個ImageBanner中的 

public void printBanner(Environment environment, Class<?> sourceClass,PrintStream out) 

最後會調用到

private void printBanner(BufferedImage image, int margin, boolean invert,
        PrintStream out) {
    AnsiElement background = (invert ? AnsiBackground.BLACK : AnsiBackground.DEFAULT);
    out.print(AnsiOutput.encode(AnsiColor.DEFAULT));
    out.print(AnsiOutput.encode(background));
    out.println();
    out.println();
    AnsiColor lastColor = AnsiColor.DEFAULT;
    for (int y = 0; y < image.getHeight(); y++) {
        for (int i = 0; i < margin; i++) {
            out.print(" ");
        }
        for (int x = 0; x < image.getWidth(); x++) {
            Color color = new Color(image.getRGB(x, y), false);
            AnsiColor ansiColor = AnsiColors.getClosest(color);
            if (ansiColor != lastColor) {
                out.print(AnsiOutput.encode(ansiColor));
                lastColor = ansiColor;
            }
            out.print(getAsciiPixel(color, invert));
        }
        out.println();
    }
    out.print(AnsiOutput.encode(AnsiColor.DEFAULT));
    out.print(AnsiOutput.encode(AnsiBackground.DEFAULT));
    out.println();
}

通過字符數組把解析圖片得到的值進行替換。最後打印的Banner。



圖片的原型


5.打印自定義文本和圖片

只需要在resources中添加Banner.txt,然後在application.yml中配置上圖片,就可以兩個都加載。



具體的關閉打印或者打印在log中,

參考https://blog.csdn.net/u014740338/article/details/68502907

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章