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是个枚举类包括三个值:

SpringBoot实战分析(五)Banner(Logo)加载与配置_第1张图片

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循环得到是那种图片。然后处理。

SpringBoot实战分析(五)Banner(Logo)加载与配置_第2张图片

如果不做配置,默认情况下这个方法会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。

SpringBoot实战分析(五)Banner(Logo)加载与配置_第3张图片

默认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)

SpringBoot实战分析(五)Banner(Logo)加载与配置_第4张图片

这个自定义的文件只是影响了下面这个方法,因为他不在是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,

SpringBoot实战分析(五)Banner(Logo)加载与配置_第5张图片

控制台打印:


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。

SpringBoot实战分析(五)Banner(Logo)加载与配置_第6张图片

SpringBoot实战分析(五)Banner(Logo)加载与配置_第7张图片

图片的原型

SpringBoot实战分析(五)Banner(Logo)加载与配置_第8张图片

5.打印自定义文本和图片

只需要在resources中添加Banner.txt,然后在application.yml中配置上图片,就可以两个都加载。

SpringBoot实战分析(五)Banner(Logo)加载与配置_第9张图片


具体的关闭打印或者打印在log中,

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

你可能感兴趣的