0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Banner的输出打印过程

科技绿洲 来源:Java技术指北 作者:Java技术指北 2023-10-13 11:25 次阅读

今天,我给大家来讲讲如何让你的 Spring Boot 屌炸天,自定义 banner 。有些新入门的朋友可能会不知道 banner 是什么?它在哪里?我在哪里见过它吗?这3连门是不是很有意思。我们今天所说的 banner 如下图所示,想必大家在启动 Spring Boot 项目的时候,大家都见过吧。

图片

大家可能都见过永不宕机的佛祖的 banner 图片吧。下图,大家应该都很熟悉吧。

图片

今天我就来带大家来看看源码,看看这个 banner 到底是怎么实现的。

Spring Boot 内置 3 种 Banner打印方式

从下图可以看出,Spring Boot 支持打印的Banner 方式有3种, SpringBootBanner 是Spring Boot 默认的 Banner 打印方式, ResouceBanner 是文本类型的 Banner 打印方式, ImageBanner 是图片类型的 Banner 打印方式。

图片

我们来看看 Banner 接口,从下方的代码,我们可以了解到,Banner 接口包含一个 printBanner 的方法 和 Mode 的枚举,Mode 包含三种状态,其中 OFF 表示不打印 Banner , LOG 表示把 Banner 输出到日志文件中, CONSOLE 表示输出到控制台,也是我们比较常见的方式。

@FunctionalInterface
public interface Banner {
    void printBanner(Environment environment, Class< ? > sourceClass, PrintStream out);
    enum Mode {
        OFF,
        CONSOLE,
        LOG
    }
}

Banner 打印流程

从 SpringApplication 类的 run 方法可以看出,printBanner 方法在 prepareEnvironment 之后,这是因为 application.properties 中有一些关于 Banner 的配置项。需要先解析 application.properties 的值,并将其绑定到对应的 bean 之后,再进行后续的操作。

public ConfigurableApplicationContext run(String... args) {
    ...
    ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
    configureIgnoreBeanInfo(environment);
    // 打印 Banner
    Banner printedBanner = printBanner(environment);
    ...
}
private Banner printBanner(ConfigurableEnvironment environment) {
    if (this.bannerMode == Banner.Mode.OFF) {
        return null;
    }
    ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
        : new DefaultResourceLoader(null);
    SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
    if (this.bannerMode == Mode.LOG) {
        return bannerPrinter.print(environment, this.mainApplicationClass, logger);
    }
    return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}

printBanner 具体的流程如下:

  1. 判断 bannerMode,如果是 OFF,表示不打印。如果是 LOG,表示打印到文件,否则打印到控制台。
  2. SpringApplicationBannerPrinter 依据指定位置是是否存在文件,判断 Banner 类型是文本还是图片,文本类型使用 ResourceBanner, 图片类型使用 ImageBanner, 如果都不是,使用 Spring Boot 默认的 SpringBootBanner。
  3. SpringApplicationBannerPrinter#print 方法调用 Banner 对象的的 printBanner 方法。不同类型的 Banner 的 printBanner 方法实现不同。

如下是 Banner 对象的获得方法,可以看出,Spring Boot 首先获得 ImageBanner,然后是 ResourceBanner,需要注意的是,这两者可以同时存在,此时会一次性打印两种 Banner。如果都不满足,还会去获得 fallbackBanner,这个是用户自己设定的 Banner,但是我们基本很少使用,大部分情况我们使用了 Spring Boot 内置的 SpringBootBanner。

class SpringApplicationBannerPrinter {
    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;
        }
        return DEFAULT_BANNER;
    }
    private Banner getTextBanner(Environment environment) {
        String location = environment.getProperty(BANNER_LOCATION_PROPERTY, DEFAULT_BANNER_LOCATION);
        Resource resource = this.resourceLoader.getResource(location);
        try {
            if (resource.exists() && !resource.getURL().toExternalForm().contains("liquibase-core")) {
                return new ResourceBanner(resource);
            }
        }
        catch (IOException ex) {
            // Ignore
        }
        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;
        }
        for (String ext : IMAGE_EXTENSION) {
            Resource resource = this.resourceLoader.getResource("banner." + ext);
            if (resource.exists()) {
                return new ImageBanner(resource);
            }
        }
        return null;
    }
}

如何关闭 Spring Boot 的 Banner

从 SpringApplication#printBanner 方法可以看出。当我们将 bannerMode 设置为 Banner.Mode.OFF 的时候,该方法返回 null,也就是此时不会打印 Banner。所以只要设置 bannerMode 为 OFF ,我们就能关闭 Banner 功能。

private Banner printBanner(ConfigurableEnvironment environment) {
  if (this.bannerMode == Banner.Mode.OFF) {
    return null;
  }
  ...
}

第一种就是在启动代码中设置。如下所示。

public static void main(String[] args) {
        SpringApplication app
                = new SpringApplication(HelloApplication.class);
        app.setBannerMode(Banner.Mode.OFF);
        app.run(args);
}

第二种是在 application.properties 中配置 spring.main.banner-mode

spring.main.banner-mode=off

这两种方式都可以关闭 Banner,那当它们同时存在的时候,哪个生效呢?我们可以这样分析,启动代码中调用 setBannerMode 方法,改变了 bannerMode 的值,之后 SpringApplication 对象执行 run 方法,在 run 方法中会解析 application.properties 的值,并将其绑定到对应的 bean,后者覆盖前者,所以 application.properties 中的配置优先级更高。

自定义文本类型的 Banner

Spring Boot 中自定义文本类型的 Banner 很简单,我们只要在 resources 下增加一个 banner.txt 就可以了。比如我想让 Banner 显示 永不宕机的佛祖雕像。那我就可以在 banner.txt 中增加以下文本。

////////////////////////////////////////////////////////////////////  
//                          _ooOoo_                               //  
//                         o8888888o                              //  
//                         88" . "88                              //  
//                         (| ^_^ |)                              //  
//                         O  =  /O                              //  
//                      ____/`---'____                           //  
//                    .'  |     |//  `.                         //  
//                   /  |||  :  |||//                          //  
//                  /  _||||| -:- |||||-                         //  
//                  |   |   -  /// |   |                       //  
//                  | _|  ''---/''  |   |                       //  
//                    .-__  `-`  ___/-. /                       //  
//                ___`. .'  /--.--  `. . ___                     //  
//              ."" '<  `.____<| >_/___.'  >'"".                  //  
//            | | :  `- `.;` _ /`;.`/ - ` : | |                 //  
//               `-.   _ __ /__ _/   .-` /  /                 //  
//      ========`-.____`-.________/___.-`____.-'========         //  
//                           `=---='                              //  
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //  
//            佛祖保佑       永不宕机      永无BUG                  //
////////////////////////////////////////////////////////////////////

打印结果是这样的

图片

如果我们想打印彩色的 banner 出来呢?在Spring Boot 中我们可以利用 AnsiColor 类来实现,我们可以在 banner.txt 中使用 AnsiColor 指定后续的文本的颜色。

${AnsiColor.YELLOW}
////////////////////////////////////////////////////////////////////
//                          _ooOoo_                               //
//                         o8888888o                              //
//                         88" . "88                              //
//                         (| ^_^ |)                              //
//                         O  =  /O                              //
//                      ____/`---'____                           //
//                    .'  |     |//  `.                         //
//                   /  |||  :  |||//                          //
//                  /  _||||| -:- |||||-                         //
//                  |   |   -  /// |   |                       //
//                  | _|  ''---/''  |   |                       //
//                    .-__  `-`  ___/-. /                       //
//                ___`. .'  /--.--  `. . ___                     //
//              ."" '<  `.____<| >_/___.'  >'"".                  //
//            | | :  `- `.;` _ /`;.`/ - ` : | |                 //
//               `-.   _ __ /__ _/   .-` /  /                 //
//      ========`-.____`-.________/___.-`____.-'========         //
//                           `=---='                              //
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
//            佛祖保佑       永不宕机      永无BUG                    //
////////////////////////////////////////////////////////////////////

如下是最终的结果

图片

public class ResourceBanner implements Banner {
    @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));
            for (PropertyResolver resolver : getPropertyResolvers(environment, sourceClass)) {
                banner = resolver.resolvePlaceholders(banner);
            }
            out.println(banner);
        }
        catch (Exception ex) {
            logger.warn(LogMessage.format("Banner not printable: %s (%s: '%s')", this.resource, ex.getClass(),
                    ex.getMessage()), ex);
        }
    }
    protected List< PropertyResolver > getPropertyResolvers(Environment environment, Class< ? > sourceClass) {
        List< PropertyResolver > resolvers = new ArrayList<  >();
        resolvers.add(environment);
        resolvers.add(getVersionResolver(sourceClass));
        resolvers.add(getAnsiResolver());
        resolvers.add(getTitleResolver(sourceClass));
        return resolvers;
    }
}

我们通过上述代码来看看,Spring Boot 为什么能打印出带颜色的 banner, ResourceBanner 将读取到的文本流转换为一串字符串。再通过4个解析器,来处理待输出的 Banner 内容。

四个解析器分别是:

  • environment 对应 application.properties 中的配置;
  • VersionResolver 解析 spring boot 版本,
  • AnsiResolver 解析颜色或字体等样式配置,
  • TitleResolver 解析当前应用的版本,名称等。

Banner图在线生成

在线生成 banner 的地址:

  • https://www.bootschool.net/ascii
  • http://www.network-science.de/ascii/
  • http://patorjk.com/software/taag//
  • http://www.degraeve.com/img2txt.php

总结

本文主要讲述了Banner的输出打印过程,如何打印个性化的文本 Banner。ImageBanner 没在本文详细说明,有兴趣的朋友可以查看阅读源码,也比较简单,也有助于你了解 Java 如何实现图片转文本的知识点。通过本文的知识点,你也可以根据自己的要求来实现 Banner, 设置为 fallbackBanner, 从而达到完全个性化的自定义 Banner 的效果。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    7639

    浏览量

    148495
  • 打印
    +关注

    关注

    1

    文章

    61

    浏览量

    18602
  • Banner
    +关注

    关注

    0

    文章

    4

    浏览量

    7449
  • 日志
    +关注

    关注

    0

    文章

    126

    浏览量

    10525
收藏 人收藏

    评论

    相关推荐

    福禄克红外热像仪:如何控制3D打印工艺

    3D打印过程中,由于速度、距离、材料等特性的不同,在粉末逐层堆叠累积的过程中,温度会出现异常,如跳变、过高、过低、不均匀等,造成打印后的结构件性能下降,韧度差、弹性不够、变脆、隐纹等。使用大师之选系列热像仪在可以为金属
    发表于 05-08 07:21

    AB32VG1开发板开发环境搭建和串口调试打印过程

    有幸申请到开发板,下面说下开发环境搭建和串口调试打印过程1:先下载RTT studio开发工具,RTT studio下载地址2:下载完成后,需要测试帐号才可以登录IDE,这部分略过3:新建RTT工程
    发表于 10-10 17:29

    东芝数码复印机复印过程概述

    东芝数码复印机复印过程概述: 充电: 将负电荷充至感光鼓的表面。 原稿曝光: 利用光照射原稿,将原稿上的图像转换为
    发表于 01-18 11:32 857次阅读

    东芝数码复印机复印过程详述

    东芝数码复印机复印过程详述 1 、感光鼓 感光鼓包括两层。外层是由有机光敏导体( OPC )制造的光敏层,内
    发表于 01-18 11:35 924次阅读

    东芝数码复印机原理与复印过程概述

    东芝数码复印机原理与复印过程概述 复印过程概述: 充电: 将负电荷充至感光鼓的表面。 原稿曝光: 利用光照射原稿,将
    发表于 01-18 11:44 2494次阅读

    什么是Banner

    什么是Banner  英文缩写: Banner 中文译名: 网页标识 分  类: IP与多媒体 解  释: 网页标识通常被用作横
    发表于 02-22 11:13 962次阅读

    红外热像仪在3D打印技术中的应用

    3D打印过程中,由于速度、距离、材料等特性的不同,在粉末逐层堆叠累积的过程中,温度会出现异常,如跳变、过高、过低、不均匀等,造成打印后的结构件性能下降,韧度差、弹性不够、变脆、隐纹等。使用大师之选系
    发表于 10-27 17:48 11次下载
    红外热像仪在3D<b class='flag-5'>打印</b>技术中的应用

    打印机如何取消打印任务

    如果文档正在打印过程中需要取消打印任务,则直接点击打印任务窗口中的“暂停”按钮即可取消打印任务。也可能通过点击Windows任务栏右下角的打印
    的头像 发表于 04-12 16:10 6.6w次阅读

    印过程中网会出现哪些故障

    丝网印刷是孔版印刷术中的一种主要印刷方法。印版呈网状,印刷时印版上的油墨在刮墨板的挤压下从版面通孔部分漏印至承印物上。网版方面的故障,有制网版时产生的问题,也有网印过程中网版产生的问题,本文仅就网印过程中网会出现哪些故障。
    的头像 发表于 05-07 14:37 2550次阅读

    胶印技术工艺参数会如何影响胶印过程

    在SMT贴片加工厂中,大多数使用胶印技术的客户在锡膏印刷技术方面往往都是非常有经验的。胶印技术相关工艺参数的确定可以以锡膏印刷技术的工艺参数作为参考。下面浅谈印刷工艺参数是如何影响胶印过程的。
    的头像 发表于 10-24 11:33 3130次阅读

    3D打印过程中会遇到哪些问题

    3D打印俗称增材制造,是一种可快速成型技术。它按照电子模型图的指示,采用分层加工、叠加成形的方式逐层增加材料来打印目标物体。特别是在小批量生产中,3D打印是一种相对快速且经济有效的生产方式零件符合
    的头像 发表于 03-22 17:23 4142次阅读

    计算机视觉算法在监测金属3D打印过程中产生的缺陷

    卡内基梅隆大学工程学院(CMU)的两位研究人员已经想出了如何将3D打印和机器学习结合起来进行实时过程监控,这种做法可以检测出零件在3D打印过程中的异常情况。
    的头像 发表于 12-26 12:51 350次阅读

    如何避免3D打印机使用过程中出现拉丝

    当我们在使用3d打印打印模型时,打印过程中有时会在模型上出现丝状塑料,尤其是当喷嘴从一端直接跳到另一端时。我们将3d打印过程中出现的这些细丝现象统称为“拉丝”。在大多数3d
    发表于 09-10 16:33 2842次阅读

    为什么在金属 3D 打印过程中使用氧气分析仪很重要?

    钛和铝。对于航空航天、汽车和医疗等行业,产品的质量在金属 3D 打印过程中不会因氧气的存在而受损,这一点至关重要。
    的头像 发表于 08-19 10:50 1046次阅读
    为什么在金属 3D <b class='flag-5'>打印过程</b>中使用氧气分析仪很重要?

    晶振在3D打印技术中的应用都有哪些?

    3D打印过程中,需要进行大量的数据处理,包括模型的切片、打印路径的规划等。
    的头像 发表于 03-17 11:29 268次阅读