【Spring Boot 源码学习】自定义 Banner 信息打印

Spring Boot 源码学习系列

在这里插入图片描述

自定义 Banner 信息打印

  • 引言
  • 往期内容
  • 主要内容
    • 1. ResourceBanner 打印
      • 1.1 添加默认的 banner.txt 资源文件
      • 1.2 指定任意路径的资源文件
      • 1.3 添加自定义的信息
    • 2. ImageBanner 打印
      • 2.1 添加默认的图像资源文件
      • 2.2 指定任意路径的图像资源文件
      • 2.3 添加自定义的图像显示信息
        • 2.3.1 添加 Banner 图像宽度属性
        • 2.3.2 添加 Banner 图像高度属性
        • 2.3.3 添加 Banner 图像外边距属性
        • 2.3.4 添加 Banner 图像是否反转图片颜色的属性
        • 2.3.5 添加 Banner 图像位深度的属性
        • 2.3.6 添加 Banner 图像像素模式的属性
    • 3. Banners 打印
    • 4. 自定义 Banner 接口实现
  • 总结

引言

上篇博文,Huazie 带大家了解了完整的 Banner 信息打印流程。相信大家都跃跃一试了,那么本篇就以这些基础的知识,来自定义 Banner 信息打印。

注意: 以下涉及 Spring Boot 源码 均来自版本 2.7.9,其他版本有所出入,可自行查看源码。

在这里插入图片描述

往期内容

在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】:

Spring Boot 源码学习
Spring Boot 项目介绍
Spring Boot 核心运行原理介绍
【Spring Boot 源码学习】@EnableAutoConfiguration 注解
【Spring Boot 源码学习】@SpringBootApplication 注解
【Spring Boot 源码学习】走近 AutoConfigurationImportSelector
【Spring Boot 源码学习】自动装配流程源码解析(上)
【Spring Boot 源码学习】自动装配流程源码解析(下)
【Spring Boot 源码学习】深入 FilteringSpringBootCondition
【Spring Boot 源码学习】OnClassCondition 详解
【Spring Boot 源码学习】OnBeanCondition 详解
【Spring Boot 源码学习】OnWebApplicationCondition 详解
【Spring Boot 源码学习】@Conditional 条件注解
【Spring Boot 源码学习】HttpEncodingAutoConfiguration 详解
【Spring Boot 源码学习】RedisAutoConfiguration 详解
【Spring Boot 源码学习】JedisConnectionConfiguration 详解
【Spring Boot 源码学习】初识 SpringApplication
【Spring Boot 源码学习】Banner 信息打印流程

主要内容

1. ResourceBanner 打印

通过 SpringApplicationBannerPrinter##getTextBanner 方法的源码了解,我们现在可以进行如下的操作:

1.1 添加默认的 banner.txt 资源文件

当没有配置 spring.banner.location 属性,Spring Boot 默认就会加载资源根目录的 banner.txt 文件,如果存在该资源文件,则会使用 ResourceBanner 打印 Banner 信息。

下面我们在新建的 demo 项目的资源根目录添加名为 banner.txt 的资源文件,如下图所示:

在这里插入图片描述

然后,直接运行我们的 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

1.2 指定任意路径的资源文件

现在我们把上面的 banner.txt 移到资源根目录新建的 banner 目录里,并更名为 mybanner.txt,如下图所示:

在这里插入图片描述

接着,在 application.properties 中配置如下:

# Banner 资源文件路径
spring.banner.location=classpath:banner/mybanner.txt

然后,还是直接运行我们的 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

1.3 添加自定义的信息

查看 ResourceBanner 的源码,我们可以看到如下的代码:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里就不得不提 PropertyResolver,它是 Spring 框架中的一个组件,主要用于解析各种属性源的属性值。它能够处理多种类型的底层源,包括properties 文件、yaml 文件,甚至是一些 nosql 数据库【因为这些数据源同样采用 key-value 形式存储数据】。

查看 PropertyResolverAPI 中,我可以看到它定义了一系列读取、解析和判断是否包含指定属性的方法。此外,它还支持以 ${propertyName:defaultValue} 格式的属性占位符,替换为实际的值的功能,这在动态配置中非常有用。

接下来,我们在 application.properties 中配置如下:

在这里插入图片描述

然后,我们在 banner.txt 中可以添加如下属性占位符:

在这里插入图片描述

最后,运行我们的 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

2. ImageBanner 打印

通过 SpringApplicationBannerPrinter##getImageBanner 方法的源码了解,我们现在可以进行如下的操作:

2.1 添加默认的图像资源文件

当没有配置 spring.banner.image.location 属性,Spring Boot 默认就会加载资源根目录的 banner.gifbanner.jpgbanner.png 等文件,如果存在其中某个资源文件,则会使用 ImageBanner 打印 Banner 信息。

下面我们在新建的 demo 项目的资源根目录添加名为 banner.gif 的资源文件,如下图所示:

在这里插入图片描述

然后,同样运行我们的 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

换成另外两个 banner.jpgbanner.png 也是能够加载的,如下:
在这里插入图片描述
在这里插入图片描述

默认 Banner 图像资源的加载逻辑:

  • 存在 banner.gif,则只加载 banner.gif
  • 不存在 banner.gif,存在 banner.jpg,则只加载 banner.jpg
  • 不存在 banner.gif,也不存在 banner.jpg,则加载 banner.png

2.2 指定任意路径的图像资源文件

现在我们把上面的 banner.png 移到资源根目录新建的 banner 目录里,并更名为 mybanner.png,如下图所示:

在这里插入图片描述

接着,在 application.properties 中配置如下:

# Banner 图像资源文件路径
spring.banner.image.location=classpath:banner/mybanner.png

然后,我们运行 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

2.3 添加自定义的图像显示信息

查看 ImageBanner 的源码,我们可以看到如下的代码:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

从上述源码,我们看到 ImageBanner 里面可以自定义一些图像的显示属性,比如:

  • spring.banner.image.width :设置 banner 图像的宽度,默认为 76 像素

  • spring.banner.image.height :设置 banner 图像的高度,默认按照宽度计算缩放比例,重新计算新图像的高度。
    在这里插入图片描述

  • spring.banner.image.margin :设置 banner 图像的外边距,默认为 2 像素

  • spring.banner.image.invert :设置是否反转图片的颜色。如果设置为 true,则颜色会被反转

  • spring.banner.image.bitdepth :设置图片的位深度,默认 4 位深度,还支持 8 位深度。位深度决定了图片的颜色精度,例如8位深度表示每个像素有256种颜色,不过大多数情况下,对于 Banner 图像输出到控制台,看起来基本没啥区别。

  • spring.banner.image.pixelmode :设置图片的的像素模式,有如下两个枚举值:

    • TEXT :文本模式,适用于需要清晰、简洁的图像效果的情况。
      在这里插入图片描述
    • BLOCK :块模式,适用于需要强调图像的某些部分或突出显示特定区域的情况。
      在这里插入图片描述

下面我们就来添加这些属性,来看看效果:

2.3.1 添加 Banner 图像宽度属性
spring.banner.image.width=50

运行 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

2.3.2 添加 Banner 图像高度属性
spring.banner.image.height=20

依旧运行 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

2.3.3 添加 Banner 图像外边距属性
spring.banner.image.margin=5

同样运行 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

2.3.4 添加 Banner 图像是否反转图片颜色的属性
spring.banner.image.invert=true

继续运行 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

2.3.5 添加 Banner 图像位深度的属性
spring.banner.image.bitdepth=8

然后运行 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述
我们发现上述好像设置了该属性,展示出来的图像并没有啥差异,事实上在也的确如此,可能我们的图像比较简单。

2.3.6 添加 Banner 图像像素模式的属性
spring.banner.image.pixelmode=block

运行 DemoApplication 入口类,可见如下运行截图:
在这里插入图片描述
在这里插入图片描述

3. Banners 打印

BannersSpringApplicationBannerPrinter 的私有静态内部类,它也实现了 Banner 接口,添加多个不同的 Banner 实现。在 SpringApplicationBannerPrinter##getBanner 方法中就能看到,新建 Banners 实例,并往其中添加了 ImageBannerResourceBanner

按照 Banners 的打印顺序,先添加进去的,先打印。

在这里插入图片描述
在这里插入图片描述

我们看看 ImageBannerResourceBanner 同时生效的场景:

在这里插入图片描述

运行 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

4. 自定义 Banner 接口实现

通过阅读 SpringApplicationBannerPrinter 的源码,我们知道如果 Banners 中没有 ResourceBanner 或者 ImageBanner 中的任何一个,就会判断自身的 fallbackBanner 变量是否存在,存在则直接返回。而该 fallbackBanner 变量实际上是 SpringApplication 中的 banner 变量。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

而我们查看 SpringApplication 的源码,可以看到如下方法:

在这里插入图片描述

下面就需要我们来自定义 Banner 接口的实现:

/**
 * 自定义 Banner 接口实现
 *
 * @author huazie
 * @version 2.0.0
 * @since 2.0.0
 */
public class CustomBanner implements Banner {

    @Override
    public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
        String author = environment.getProperty("author");

        out.println(" _   _                 _      ");
        out.println("| | | |_   _  __ _ ___(_) ___ ");
        out.println("| |_| | | | |/ _` |_  / |/ _ \\");
        out.println("|  _  | |_| | (_| |/ /| |  __/");
        out.println("|_| |_|\\__,_|\\__,_/___|_|\\___|");
        out.println("                              ");
        out.println(" 作者: " + author);
        out.println();
    }
}

接下来,修改入口类 DemoApplication,如下:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(DemoApplication.class);
        springApplication.setBanner(new CustomBanner());
        springApplication.run(args);
    }
}

最后运行 DemoApplication 入口类,可见如下运行截图:

在这里插入图片描述

总结

本篇 Huazie 带大家自定义 Banner 信息打印,再次加深了对 Banner 信息打印流程的理解。当然,这只是 Spring Boot 启动过程中的一个小插曲,后续的博文我们将继续深入讲解 SpringApplication 的其他内容,敬请期待!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网站监控是什么

在当今高度互联的世界中&#xff0c;网站已成为企业和个人成功的关键因素。无论是提供产品或服务&#xff0c;还是建立品牌形象&#xff0c;网站都是不可或缺的工具。然而&#xff0c;随着互联网用户对访问速度和用户体验的高要求&#xff0c;保持网站的稳定性和可用性变得至关…

旋转的数组

分享今天看到的一个题目&#xff0c;不同思路解法 题目 思路1&#xff1a;时间复杂度0(N*k&#xff09; void rotate(int *a,int N,int k)//N为数组元素个数 { while(k--) { int tema[N-1]; for(int rightN-2;right>0;right--) { a[right1]a[right]; } a[0]tem; …

Seata的部署和集成

文章目录 一、部署Seata的tc-server1.下载2.解压3.修改配置4.在nacos添加配置5.创建数据库表6.启动TC服务 二、微服务集成seata1.引入依赖2.修改配置文件 三、TC服务的高可用和异地容灾1.模拟异地容灾的TC集群2.将事务组映射配置到nacos3.微服务读取nacos配置 一、部署Seata的t…

静态web服务器开发之HTTP协议

文章目录 版权声明HTTP协议网址HTTPS补充&#xff1a;HTTP的无状态特性浏览器访问Web服务器流程HTTP协议请求报文HTTP GET请求报文分析POST请求方式要点总结 HTTP协议响应报文HTTP 响应报文分析HTTP 状态码要点总结 HTTP协议通信过程查看 版权声明 本博客的内容基于我个人学习…

矩阵论(Matrix)

​ 大纲 矩阵微积分&#xff1a;多元微积分的一种特殊表达&#xff0c;尤其是在矩阵空间上进行讨论的时候逆矩阵(inverse matrix)矩阵分解&#xff1a;特征分解&#xff08;Eigendecomposition&#xff09;&#xff0c;又称谱分解&#xff08;Spectral decomposition&#xf…

Spark SQL 时间格式处理

初始化Spark Sql package pbcp_2023.clear_dataimport org.apache.spark.SparkConf import org.apache.spark.sql.SparkSession import org.apache.spark.sql.functions.{current_date, current_timestamp}object twe_2 {def main(args: Array[String]): Unit {val con new …

优秀的时间追踪软件Timemator for Mac轻松管理时间!

在现代社会&#xff0c;时间管理成为了我们工作和生活中的一大挑战。如果你经常感到时间不够用&#xff0c;无法高效地完成任务&#xff0c;那么Timemator for Mac将成为你的得力助手。 Timemator for Mac是一款出色的时间追踪软件&#xff0c;它可以帮助你精确记录和管理你的…

Codeforces Round 786 (Div. 3) D. A-B-C Sort

D. A-B-C Sort 步骤 1 &#xff1a;当 a不为空时&#xff0c;从 a中取出最后一个元素&#xff0c;并将其移动到数组 b的中间。如果 b 当前长度为奇数&#xff0c;则可以选择&#xff1a;将 a 中的元素放到 b 中间元素的左边或右边。结果&#xff0c; a 变空&#xff0c; b 由 n…

【2023.11.24】Mybatis基本连接语法学习➹

基本配置 1.如果使用Maven管理项目&#xff0c;需要在pom.xml中配置依赖。 2.安装Mybatis-3.5.7.jar包 3.进行XML配置&#xff1a;这里将文件命名为mybatis-config.xml 配置数据库连接XML文件 <?xml version"1.0" encoding"UTF-8" ?> <!DO…

数据结构-归并排序+计数排序

1.归并排序 基本思想&#xff1a; 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有序&#xff0c;再使子序列段间有序。若将两个有序表合并成一个…

Relabel与Metic Relabel

Prometheus支持多种方式的自动发现目标&#xff08;targets&#xff09;&#xff0c;以下是一些常见的自动发现方式&#xff1a; 静态配置&#xff1a;您可以在Prometheus配置文件中直接列出要监测的目标。这种方式适用于目标相对稳定的情况下&#xff0c;例如固定的服务器或设…

【多线程】Thread类的使用

目录 1.概述 2.Thread的常见构造方法 3.Thread的几个常见属性 4.启动一个线程-start() 5.中断一个线程 5.1通过共享的标记来进行沟通 5.2 调用 interrupt() 方法来通知 6.等待一个进程 7.获取当前线程引用 8.线程的状态 8.1所有状态 8.2线程状态和转移的意义 1.概述 …

字节序

计算机硬件有两种储存数据的方式&#xff1a;大端字节序big endian 和 小端字节序 little endian。 数值0x2211使用两个字节储存&#xff1a;高位字节是0x22&#xff0c;低位字节是0x11。 大端字节序&#xff1a;低位放高地址&#xff0c;高位字节在低地址&#xff0c;地址空间…

JDBC编程方法及细节

JDBC&#xff08;Java Database Connectivity&#xff09;是Java编程语言用于连接和操作数据库的API&#xff08;Application Programming Interface&#xff09;。它为开发人员提供了一组Java类和接口&#xff0c;用于与各种关系型数据库进行通信。使用JDBC&#xff0c;开发人…

路径规划之Best-First Search算法

系列文章目录 路径规划之Dijkstra算法 路径规划之Best-First Search算法 路径规划之Best-First Search算法 系列文章目录前言一、Best-First Search算法1.1 起源1.2 过程 三、简单使用 前言 Best-First Search算法和Dijkstra算法类似&#xff0c;都属于BFS的扩展或改进 一、…

【Python进阶笔记】md文档笔记第6篇:Python进程和多线程使用(图文和代码)

本文从14大模块展示了python高级用的应用。分别有Linux命令&#xff0c;多任务编程、网络编程、Http协议和静态Web编程、htmlcss、JavaScript、jQuery、MySql数据库的各种用法、python的闭包和装饰器、mini-web框架、正则表达式等相关文章的详细讲述。 全套md格式笔记和代码自…

【hive】列转行—collect_set()/collect_list()/concat_ws()函数的使用场景

文章目录 一、collect_set()/collect_list():二、实际运用1、创建测试表及插入数据 :举例1&#xff1a;按照id&#xff0c;cur_day分组&#xff0c;取出每个id对应的所有rule&#xff08;不去重&#xff09;。举例2&#xff1a;按照id&#xff0c;cur_day分组&#xff0c;取出每…

【Unity入门】碰撞检测

碰撞器由来 1.系统默认会给每个对象(GameObject)添加一个碰撞组件(ColliderComponent)&#xff0c;一些背景对象则可以取消该组件。 2.在unity3d中&#xff0c;能检测碰撞发生的方式有两种&#xff0c;一种是利用碰撞器&#xff0c;另一种则是利用触发器。这两种方式的应用非…

左孩子右兄弟(Java详解)

目录 一、题目描述 二、题解 一、题目描述 对于一棵多叉树&#xff0c;我们可以通过“左孩子右兄弟” 表示法&#xff0c;将其转化成一棵二叉树。 如果我们认为每个结点的子结点是无序的&#xff0c;那么得到的二叉树可能不唯一。 换句话说&#xff0c;每个结点可以选任意子结…

论文导读 | 10月专题内容精选:人的预测

编者按 本次论文导读&#xff0c;编者选择了10月份OR和MS上与"人的预测"有关的三篇文章&#xff0c;分别涉及群体智慧的提取&#xff0c;个体序列预测的评估&#xff0c;以及决策者对风险的扭曲感知在分布式鲁棒优化中的应用。其中&#xff0c;从基于"生成式可能…