自定义Springboot启动Banner

简介: 自定义Springboot启动Banner


相信使用过Springboot的朋友们肯定对于这个图不陌生,这就是Springboot服务启动时候的默认的启动Banner。

作为爱倒腾的程序员,肯定不满足一成不变的这个图,自定义是必须的,例如打印个“LOVE”,或者把你女朋友的照片打印出来。于是乎,就要弄懂Banner打印的原理以及如何自定义打印的Banner图。

一、自定义Banner

先来看看效果打印一个"I LOVE JAVA"的ASCII图形的效果,如下图

在Springboot中打印实现这样子的一个效果非常简单,只需要在类路径下(Springboot的resources文件夹下)放置banner.txt文件,文件中的内容放置这个图形的ASCII文本内容即可。

那么这样子的ASCII内容如何制作呢,其实有很多第三方的网站提供了工具,例如
https://www.bootschool.net/ascii,你可以到网站上轻松的制作并下载,可以选择各种类型的字体。

除了已经制作好的ASCII文本内容,Springboot还支持gif、jpg、png格式的图像,同样命名为banner.gif/jpg/png放置在resources文件夹下即可。

第二种实现自定义banner的选择是设置spring.banner.location属性指定要打印的文本文件的位置,或者使用
spring.banner.image.location指定图形文件的位置,如果文件所使用的不是UTF-8的编码,你还可以通过spring.banner.charset设置指定的文件编码。

注意:banner.gif/jpg/png的优先级高于banner.txt。

我们尝试将百度的Logo以banner.png的形式放置在resources目录下,重新启动应用,可以看到打印出了百度Logo的ASCII图形。

二、Banner打印的原理

根据以上过程的操作可以看到Springboot应用启动的过程中会根据设置的Banner图片或者ASCII图形进行解析,根据解析出来的图片像素点对应不同的字符,将ASCII字符打印出来。

我们追踪SpringApplicaiton.run()方法,可以看到以下的代码:

public ConfigurableApplicationContext run(String... args) {
  ......
  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);
  }

可以看到打印的功能主要由
SpringApplicationBannerPrinter.print()方法实现,我们一起来看看这个方法(以System.out分支为例):

Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
    Banner banner = getBanner(environment);
    banner.printBanner(environment, sourceClass, out);
    return new PrintedBanner(banner, sourceClass);
}
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;
  }

可以看到,实际上Springboot提供了集中不同的Banner实现,有ImageBanner、TextBanner和自定义的fallbackBanner,会根据实际的情况选择不同的Banner实现进行Banner的打印。

以ImageBanner为例,跟踪发现其最终打印的实现代码如下:

private void printBanner(Environment environment, PrintStream out) throws IOException {
    int width = getProperty(environment, "width", Integer.class, 76);
    int height = getProperty(environment, "height", Integer.class, 0);
    int margin = getProperty(environment, "margin", Integer.class, 2);
    boolean invert = getProperty(environment, "invert", Boolean.class, false);
    BitDepth bitDepth = getBitDepthProperty(environment);
    PixelMode pixelMode = getPixelModeProperty(environment);
    Frame[] frames = readFrames(width, height);
    for (int i = 0; i < frames.length; i++) {
      if (i > 0) {
        resetCursor(frames[i - 1].getImage(), out);
      }
      printBanner(frames[i].getImage(), margin, invert, bitDepth, pixelMode, out);
      sleep(frames[i].getDelayTime());
    }
  }
private void printBanner(BufferedImage image, int margin, boolean invert, BitDepth bitDepth, 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++) {
      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);
        AnsiElement ansiColor = colors.findClosest(color);
        if (ansiColor != lastColor) {
          out.print(AnsiOutput.encode(ansiColor));
          lastColor = ansiColor;
        }
        out.print(getAsciiPixel(color, invert, pixelMode));
      }
      out.println();
    }
    out.print(AnsiOutput.encode(AnsiColor.DEFAULT));
    out.print(AnsiOutput.encode(AnsiBackground.DEFAULT));
    out.println();
  }
public enum PixelMode {
    /**
     * Use text chars for pixels.
     */
    TEXT(' ', '.', '*', ':', 'o', '&', '8', '#', '@'),
    /**
     * Use unicode block chars for pixels.
     */
    BLOCK(' ', '\u2591', '\u2592', '\u2593', '\u2588');
    private char[] pixels;
    PixelMode(char... pixels) {
      this.pixels = pixels;
    }
    char[] getPixels() {
      return this.pixels;
    }
  }

可以看到对于图片像素的解析过程以及对于打印出来的字符的配置,类似的可以自己实现自定义的Banner打印类,根据自己的需要设置打印不同的字符,通过
SpringApplicaiton.setBanner(Banner banner)来使用自定义的Banner。

相关文章
|
3月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
2月前
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
215 0
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
217 2
|
22小时前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
28 14
|
23天前
|
Java Spring
SpringBoot入门 - 定制自己的Banner
SpringBoot入门 - 定制自己的Banner
15 2
SpringBoot入门 - 定制自己的Banner
|
26天前
|
Java Spring
SpringBoot入门(5) - 定制自己的Banner
SpringBoot入门(5) - 定制自己的Banner
11 0
 SpringBoot入门(5) - 定制自己的Banner
|
21天前
|
安全 Java 应用服务中间件
如何将Spring Boot应用程序运行到自定义端口
如何将Spring Boot应用程序运行到自定义端口
29 0
|
3月前
|
Java Spring
springboot静态资源目录访问,及自定义静态资源路径,index页面的访问
本文介绍了Spring Boot中静态资源的访问位置、如何进行静态资源访问测试、自定义静态资源路径和静态资源请求映射,以及如何处理自定义静态资源映射对index页面访问的影响。提供了两种解决方案:取消自定义静态资源映射或编写Controller来截获index.html的请求并重定向。
springboot静态资源目录访问,及自定义静态资源路径,index页面的访问
|
2月前
|
Java Spring
【SpringBoot】技能一之修改端口与banner样式
【SpringBoot】技能一之修改端口与banner样式
29 5
|
2月前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
75 2