• 6.SpringBoot学习(六)——Spring Boot Banner自定义


    1.简介

    1.1 概述

    The banner that is printed on start up can be changed by adding a banner.txt file to your classpath or by setting the spring.banner.location property to the location of such a file. If the file has an encoding other than UTF-8, you can set spring.banner.charset. In addition to a text file, you can also add a banner.gif, banner.jpg, or banner.png image file to your classpath or set the spring.banner.image.location property. Images are converted into an ASCII art representation and printed above any text banner.

    banner 是在启动时打印的内容,可以通过在 classpath 下添加 “ banner.txt” 文件或 设置“ spring.banner.location” 属性值来改变 banner 的内容。如果文件的编码不是UTF-8,则可以通过spring.banner.charset 进行设置。除了文本文件之外,您还可以在 classpath 下添加 banner.gifbanner.jpgbanner.png 图像文件或设置 spring.banner.image.location 属性。图片将被转换为 ASCII 的形式进行展现并在文本内容之前打印。

    1.2 特点

    banner.txt 可以包含如下内容

    Variable Description
    ${application.version} The version number of your application, as declared in MANIFEST.MF. For example, Implementation-Version: 1.0 is printed as 1.0.
    ${application.formatted-version} The version number of your application, as declared in MANIFEST.MF and formatted for display (surrounded with brackets and prefixed with v). For example (v1.0).
    ${spring-boot.version} The Spring Boot version that you are using. For example 2.2.8.RELEASE.
    ${spring-boot.formatted-version} The Spring Boot version that you are using, formatted for display (surrounded with brackets and prefixed with v). For example (v2.2.8.RELEASE).
    ${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME}) Where NAME is the name of an ANSI escape code. See AnsiPropertySource for details.
    ${application.title} The title of your application, as declared in MANIFEST.MF. For example Implementation-Title: MyApp is printed as MyApp.

    The SpringApplication.setBanner(…) method can be used if you want to generate a banner programmatically. Use the org.springframework.boot.Banner interface and implement your own printBanner() method.

    You can also use the spring.main.banner-mode property to determine if the banner has to be printed on System.out (console), sent to the configured logger (log), or not produced at all (off).

    2.演示环境

    1. JDK 1.8.0_201
    2. Spring Boot 2.2.0.RELEASE、Spring Cloud Hoxton.RELEASE
    3. 构建工具(apache maven 3.6.3)
    4. 开发工具(IntelliJ IDEA )

    3.演示代码

    3.1 代码说明

    自定义 banner.txt,在项目启动时打印自定义 banner

    3.2 代码结构

    image-20200713193628565

    3.3 maven 依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    

    3.4 配置文件

    application.properties

    application.version=0.0.1-SNAPSHOT
    application.formatted-version=0.0.1
    application.title=spring-boot-banner
    

    banner.txt

    ${application.version}
    ${application.formatted-version}
    ${application.title}
    ${AnsiColor.BRIGHT_GREEN}$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    ${AnsiColor.BRIGHT_CYAN}$$       _________  __  __/ / /_  ____ _/ / /___ _____/ /    $$
    ${AnsiColor.BRIGHT_CYAN}$$      / ___/ __ / / / / / __ / __ `/ / / __ `/ __  /     $$
    ${AnsiColor.BRIGHT_CYAN}$$     (__  ) /_/ / /_/ / / /_/ / /_/ / / / /_/ / /_/ /      $$
    ${AnsiColor.BRIGHT_CYAN}$$    /____/\____/\__,_/_/_.___/\__,_/_/_/\__,_/\__,_/       $$
    ${AnsiColor.BRIGHT_GREEN}$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                   ${AnsiColor.BRIGHT_RED}Spring Boot: ${spring-boot.formatted-version}
    
    

    3.6 git 地址

    spring-boot/spring-boot-05-basis/spring-boot-banner

    4.测试

    启动 SpringBootBannerApplication.main 方法,打印出 banner.txt 中内容

    image-20200713193939809

    5.源码分析

    5.1 banner 如何打印的?

    banner 是如何打印的呢?

    在 spring boot 项目启动时,调用 run 方法,最终会调用到 printBanner 方法

    public ConfigurableApplicationContext run(String... args) {
        // ...
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
            configureIgnoreBeanInfo(environment);
            // 打印 banner
            Banner printedBanner = printBanner(environment);
            // ...
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }
    
        //...
        return context;
    }
    

    它的实现如下

    private Banner printBanner(ConfigurableEnvironment environment) {
        // 如果关闭 banner,直接返回
        if (this.bannerMode == Banner.Mode.OFF) {
            return null;
        }
        // 默认 resourceLoader=null,使用 DefaultResourceLoader
        ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
            : new DefaultResourceLoader(getClassLoader());
        SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
        // bannerMode 有3中取值,OFF、CONSOLE、LOG,这里默认为 CONSOLE
        if (this.bannerMode == Mode.LOG) {
            return bannerPrinter.print(environment, this.mainApplicationClass, logger);
        }
        // 打印 banner
        return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
    }
    

    bannerPrinter.print

    Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
        // 获取 banner,先获获取图片类型,再获取文本类型,都没有则答应 Spring Boot
        Banner banner = getBanner(environment);
        // 如果有多种类型,循环打印;按照添加顺序,先图片再文本
        banner.printBanner(environment, sourceClass, out);
        return new PrintedBanner(banner, sourceClass);
    }
    

    banner.printBanner

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

    这里看下文本打印,ResourceBanner.printBanner

    @Override
    public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
        try {
            // 获取编码格式
            String banner = StreamUtils.copyToString(this.resource.getInputStream(),
                                                     environment.getProperty("spring.banner.charset", Charset.class, StandardCharsets.UTF_8));
    		// 处理 banner 文件中属性值
            for (PropertyResolver resolver : getPropertyResolvers(environment, sourceClass)) {
                banner = resolver.resolvePlaceholders(banner);
            }
            // 使用 java bio 进行打印
            out.println(banner);
        }
        catch (Exception ex) {
            logger.warn(
                "Banner not printable: " + this.resource + " (" + ex.getClass() + ": '" + ex.getMessage() + "')",
                ex);
        }
    }
    

    6.参考

    1. 官方文档-Spring Boot Features/Banner
  • 相关阅读:
    并发容器和框架之ConcurrentHashMap
    Java的LockSupport工具,Condition接口和ConditionObject
    从源码来看ReentrantLock和ReentrantReadWriteLock
    VMWARE虚拟机上Terminal中使用sudo出现”** 不在sudoers文件中,此事将被警告 “错误
    mac下idea运行项目慢问题解决
    Idea 只修改编辑区主题
    redis内部数据结构的数据结构
    mysql存储过程详解
    HashMap中resize()剖析
    谈Redis的refash的增量式扩容
  • 原文地址:https://www.cnblogs.com/col-smile/p/13295308.html
Copyright © 2020-2023  润新知