SpringBoot入门 - 定制自己的Banner

news2025/1/12 15:54:56
我们在启动Spring Boot程序时,有SpringBoot的Banner信息,那么如何自定义成自己项目的信息呢?

什么是Banner

我们在启动Spring Boot程序时,有如下Banner信息:

那么如何自定义成自己项目的名称呢?

如何更改Banner

更改Banner有如下几种方式:
  • banner.txt配置(最常用)

在application.yml中添加配置

spring:
  banner:
    charset: UTF-8
    location: classpath:banner.txt

在resource下创建banner.txt,内容自定义:

----welcome----

---------------

修改后,重启的app的效果

  • SpringApplication启动时设置参数

SpringApplication application = new SpringApplication(App.class);
/**
* Banner.Mode.OFF:关闭;
* Banner.Mode.CONSOLE:控制台输出,默认方式;
* Banner.Mode.LOG:日志输出方式;
*/
application.setBannerMode(Banner.Mode.OFF); // here
application.run(args);

SpringApplication还可以设置自定义的Banner的接口类

文字Banner的设计

如何设计上面的文字呢?

一些设计Banner的网站

可以通过这个网站进行设计:patorjk Banner

比如:

我们修改banner.txt, 运行的效果如下

IDEA中Banner的插件

IDEA中也有插件,不过没有预览功能

其它工具

http://www.network-science.de/ascii/

http://www.degraeve.com/img2txt.php

http://www.bootschool.net/ascii

Banner中其它配置信息

除了文件信息,还有哪些信息可以配置呢?比如Spring默认还带有SpringBoot当前的版本号信息。

在banner.txt中,还可以进行一些设置:

# springboot的版本号 
${spring-boot.version}             
 
# springboot的版本号前面加v后上括号 
${spring-boot.formatted-version}

# MANIFEST.MF文件中的版本号 
${application.version}              
 
# MANIFEST.MF文件的版本号前面加v后上括号 
${application.formatted-version}

# MANIFEST.MF文件中的程序名称
${application.title}

# ANSI样色/样式等
${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME})

简单的测试如下(注意必须打包出Jar, 才会生成resources/META-INF/MANIFEST.MF):

动画Banner的设计

那我能不能设置动态的Banner呢?比如一个图片?

SpringBoot2是支持图片形式的Banner,

spring:
  main:
    banner-mode: console
    show-banner: true
  banner:
    charset: UTF-8
    image:
      margin: 0
      height: 10
      invert: false
      location: classpath:pdai.png

效果如下(需要选择合适的照片,不然效果不好, 所以这种方式很少使用),

注意: 格式不能太大,不然会报错

org.springframework.boot.ImageBanner     : Image banner not printable: class path resource [banner.gif] (class java.lang.ArrayIndexOutOfBoundsException: '4096')

进一步思考

图片Banner是如何起作用的?

发现 Springboot 可以把图片转换成 ASCII 图案,那么它是怎么做的呢?以此为例,我们看下Spring 的Banner是如何生成的呢?
  • 获取Banner

  • 优先级是环境变量中的Image优先,格式在IMAGE_EXTENSION中

  • 然后才是banner.txt

  • 没有的话就用SpringBootBanner

  • 如果是图片

  • 获取图片Banner(属性配置等)

  • 转换成ascii

获取banner

class SpringApplicationBannerPrinter {
    static final String BANNER_LOCATION_PROPERTY = "spring.banner.location";
    static final String BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location";
    static final String DEFAULT_BANNER_LOCATION = "banner.txt";
    static final String[] IMAGE_EXTENSION = new String[]{"gif", "jpg", "png"};
    private static final Banner DEFAULT_BANNER = new SpringBootBanner(); // 默认的Spring Banner
    private final ResourceLoader resourceLoader;
    private final Banner fallbackBanner;

    // 获取Banner,优先级是环境变量中的Image优先,格式在IMAGE_EXTENSION中,然后才是banner.txt
    private Banner getBanner(Environment environment) {
        SpringApplicationBannerPrinter.Banners banners = new SpringApplicationBannerPrinter.Banners();
        banners.addIfNotNull(this.getImageBanner(environment));
        banners.addIfNotNull(this.getTextBanner(environment));
        if (banners.hasAtLeastOneBanner()) {
            return banners;
        } else {
            return this.fallbackBanner != null ? this.fallbackBanner : DEFAULT_BANNER;
        }
    }

获取图片Banner

private Banner getImageBanner(Environment environment) {
    String location = environment.getProperty("spring.banner.image.location");
    if (StringUtils.hasLength(location)) {
        Resource resource = this.resourceLoader.getResource(location);
        return resource.exists() ? new ImageBanner(resource) : null;
    } else {
        String[] var3 = IMAGE_EXTENSION;
        int var4 = var3.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String ext = var3[var5];
            Resource resource = this.resourceLoader.getResource("banner." + ext);
            if (resource.exists()) {
                return new ImageBanner(resource);
            }
        }

        return null;
    }
}

获取图片的配置等

private void printBanner(Environment environment, PrintStream out) throws IOException {
    int width = (Integer)this.getProperty(environment, "width", Integer.class, 76);
    int height = (Integer)this.getProperty(environment, "height", Integer.class, 0);
    int margin = (Integer)this.getProperty(environment, "margin", Integer.class, 2);
    boolean invert = (Boolean)this.getProperty(environment, "invert", Boolean.class, false); // 图片的属性
    BitDepth bitDepth = this.getBitDepthProperty(environment);
    ImageBanner.PixelMode pixelMode = this.getPixelModeProperty(environment);
    ImageBanner.Frame[] frames = this.readFrames(width, height); // 读取图片的帧

    for(int i = 0; i < frames.length; ++i) {
        if (i > 0) {
            this.resetCursor(frames[i - 1].getImage(), out);
        }

        this.printBanner(frames[i].getImage(), margin, invert, bitDepth, pixelMode, out);
        this.sleep(frames[i].getDelayTime());
    }

}

转换成ascii

private void printBanner(BufferedImage image, int margin, boolean invert, BitDepth bitDepth, ImageBanner.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) {
        int x;
        for(x = 0; x < margin; ++x) {
            out.print(" ");
        }

        for(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(this.getAsciiPixel(color, invert, pixelMode)); // // 像素点转换成字符输出
        }

        out.println();
    }

    out.print(AnsiOutput.encode(AnsiColor.DEFAULT));
    out.print(AnsiOutput.encode(AnsiBackground.DEFAULT));
    out.println();
}

示例源码

https://download.csdn.net/download/DeveloperFire/87519876

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/384738.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一天约了4个面试,复盘一下面试题和薪资福利

除了最新的面经分享&#xff0c;还有字节大佬的求职面试答疑&#xff0c;告诉你关键问题是什么&#xff1f;少走弯路。**另外本文也汇总了6份大厂面试题&#xff1a;字节、腾讯、小米、腾讯云、滴滴、小米游戏。**希望对大家有帮助。 前言 昨天我的交流群里&#xff0c;有位宝…

【学习笔记】深入理解JVM之对象的实例化

参考尚硅谷JVM 102 - 106 集 首发地址&#xff1a;地址 1、JVM对象的实例化 1.1 对象的创建方式 对象有一下几种创建对象的方式 new Object object new Object();Class的newInstance() Object object Object.class.newInstance();Constructor的newInstance&#xff08…

精选博客系列|公用事业中的VMware:在边缘重新定义价值

VMware 已经成为公用事业行业的核心。您可以在那里找到例如 VMware vSphere&#xff08;包括基础 Hypervisor ESXi 和 VMware vCenter 建立的整体控制平面&#xff09;的核心产品。来自软件定义的基础架构带来的诸多好处使 IT 团队将其先前基于硬件的系统转变为 VMware Cloud F…

GPT+时代来临:OpenAI开放GPT3.5模型,1000token仅1毛钱

GPT3.5 Model API 使用指南 今天OpenAI公司开放了最新的GPT3.5模型&#xff1a;gpt-3.5-turbo&#xff0c;也就是目前网页版的ChatGPT使用的模型。而此前OpenAI开放的最新的模型text-davinci-003则是基于GPT3模型构建的。并且价格十分便宜&#xff1a;1000 token/0.002美元&am…

CVE-2021-2109 WebLogic JNDI 注入

0x01 前言学习一下 WebLogic JNDI 注入 RCE&#xff08;CVE-2021-2109&#xff09;0x02 环境搭建和之前 WebLogic 的环境搭建是一致的&#xff0c;本文不再赘述。不过值得一提的是&#xff0c;我的 weblogic 版本是 10.3.6&#xff1b;需要手动添加 \server\lib\consoleapp\web…

打电话,玩手机、摔倒行人行为识别

文章大纲 数据集准备一些难点paddle 解决方案行为识别打电话摔倒开源解决方案前文: 深度学习与视频分析简介视频分析:基于目标检测(YOLO)实现走路看手机检测、玩手机检测、跌倒检测等数据集准备 我们可以从开源数据中挑选一些 参考文章: 使用python 脚本挑出coco 数据集…

【C++的OpenCV】第九课-OpenCV图像常用操作(六):图像形态学-阈值的概念、功能及操作(threshold()函数))

目录一、阈值&#xff08;thresh&#xff09;的概念二、阈值在图形学中的用途三、阈值的作用和操作3.1 在OpenCV中可以进行的阈值操作3.2 操作实例3.2.1 threshold()函数介绍3.2.2 实例3.2.3 结果上节课的内容&#xff08;作者还是鼓励各位同学按照顺序进行学习哦&#xff09;&…

易基因|m6A RNA甲基化研究的数据挖掘思路:干货系列

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。关于m6A甲基化研究思路&#xff08;1&#xff09;整体把握m6A甲基化图谱特征&#xff1a;m6A peak数量变化、m6A修饰基因数量变化、单个基因m6A peak数量分析、m6A peak在基因元件上的分布…

IP协议的漏洞及防护措施

文章目录一、TCP/IP协议族二、IP协议三、IP协议的安全问题及防护措施一、TCP/IP协议族 二、IP协议 网际协议&#xff08;Internet Protocol&#xff0c;IP&#xff09;是TCP/IP协议族的核心&#xff0c;也是网际层最重要的协议。 IP数据报由首部和数据两部分组成&#xff1b…

Spark性能优化五 算子优化

文章目录&#xff08;一&#xff09;map 和 mapPartitions&#xff08;二&#xff09;foreach 和 foreachPartition&#xff08;三&#xff09;repartition的使用&#xff08;四&#xff09;reduceByKey 和 groupByKey的区别&#xff08;一&#xff09;map 和 mapPartitions m…

解决Visual C++ Redistributable安装找不到vc_runtimeMinimum_x86.msi最简单办法

今天在安装Fritzing的时候&#xff0c;遇到了需要Visual C Redistributable支持包&#xff0c;所以就动手安装&#xff0c;发现居然不能安装&#xff0c;安装几次居然错误提示所需要的安装包*.MSI的居然名称还不用。我也是下载了各种版本来试图靠运气过关&#xff0c;结果失败告…

Linux下安装prometheus grafana

1 安装prometheus1.1 下载prometheus下载地址https://prometheus.io/download/#prometheus下载wget https://github.com/prometheus/prometheus/releases/download/v2.42.0/prometheus-2.42.0.linux-amd64.tar.gz1.2 安装# 新建目录&#xff0c;并进入目标目录 mkdir -p /middl…

Java语言如何求平方根

问题 在编程时&#xff0c;会遇到求平方根的问题&#xff0c;本次问题讲到如何使用Java来求解平方根。 方法 使用java.lang.Math类的sqrt(double)方法求平方根。Math是java.lang包中的类&#xff0c;所以就可以直接使用这个类。Double为对象中的基本类型。例如求正整数16的平方…

Vue 2

文章目录1. 简介2. 第一个Vue程序3. 指令3.1 判断循环3.2 操作属性3.3 绑定事件3.4 表单中数据双向绑定3.5 其他内置指令3.6 自定义指令4. 组件4.1 全局注册4.2 局部注册4.3 组件通讯4.4 单文件组件5. 组件插槽5.1 单个插槽5.2 具名插槽5.3 作用域插槽6. 内置组件6.1 component…

智能客服系统:为企业提升客户满意度

随着科技的不断进步&#xff0c;电话营销、呼叫中心机器人、语音自助服务等领域的智能客服系统也得到了飞速的发展。这些技术的出现&#xff0c;让企业能够更加高效地管理客户服务&#xff0c;提高客户满意度&#xff0c;从而在市场竞争中占据优势。 电话营销是企业推广产品、服…

g2o源码阅读

之前写的g2o源码阅读笔记&#xff0c;分享给有需要的人 整个文档请自行下载&#xff0c;这里只贴一个图片。

微信小程序第一节 —— 自定义顶部、底部导航栏以及获取胶囊体位置信息。

一、前言 大家好&#xff01;我是 是江迪呀。我们在进行微信小程序开发时&#xff0c;常常需要自定义一些东西&#xff0c;比如自定义顶部导航、自定义底部导航等等。那么知道这些自定义内容的具体位置、以及如何适配不同的机型就变得尤为重要。下面让我以在iPhone机型&#x…

Word处理控件Aspose.Words功能演示:使用 C# 拆分 MS Word 文档

Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c; Aspose API支持流行文件格式处…

Python——列表排序和赋值

&#xff08;1&#xff09;列表排序&#xff1a; 列表排序方法 ls.sort() 对列表ls 中的数据在原地进行排序 ls [13, 5, 73, 4, 9] ls.sort()ls.sort(reverseFalse) 默认升序&#xff0c;reverseTrue&#xff0c;降序 ls [13, 5, 73, 4, 9] ls.sort(reverseTrue)key指定排序时…

小红书「高效达人筛选攻略」

三八女神节降临&#xff0c;诸多品牌纷纷开启铺垫预热&#xff0c;在各大平台借势宣传。而聚集庞大年轻女性消费群体的小红书&#xff0c;对“她营销”的重要性不言而喻。节点序幕拉开&#xff0c;面对海量达人信息&#xff0c;如何提前积草屯粮、高效备战&#xff1f; 本期千瓜…