Spring Boot banner详解

news2024/11/27 14:47:26

Spring Boot 3.x系列文章

  1. Spring Boot 2.7.8 中文参考指南(一)
  2. Spring Boot 2.7.8 中文参考指南(二)-Web
  3. Spring Boot 源码阅读初始化环境搭建
  4. Spring Boot 框架整体启动流程详解
  5. Spring Boot 系统初始化器详解
  6. Spring Boot 监听器详解
  7. Spring Boot banner详解

自定义banner

Spring Boot 默认打印的banner是这样的,Java工程师看都看腻了。
在这里插入图片描述

一般的公司如果有自己脚手架,都会选择自定义banner,放一个公司Logo或者框架别名。

简易版banner

首先生成一个自己的banner,比如我生成的
在这里插入图片描述

生成的网站很多,可以用"banner 生成器"自行搜索

把生成的内容copy到txt中,命名为"banner.txt"(UTF-8),然后放到resources下。
启动Spring Boot 即可看到效果。

在这里插入图片描述

自定义banner路径

上述的banner.txt 只能放在resources根目录下,不能在resources子目录或其他的目录,使用spring.banner.location指定该文件的路径,如果该文件不是UTF-8编码,使用spring.banner.charset指定文件编码,比如我将文件放到resources的子目录static中。

在这里插入图片描述

自定义banner 样式

光一个Logo也还是太单调,如果能再打印个Spring Boot 版本、应用程序版本就更好了,Spring Boot 都给我们提供了相关变量,可以在banner.txt中使用。

  • ${application.version} 应用程序版本
  • ${application.formatted-version} 格式化的应用程序版本,前缀是v
  • ${spring-boot.version} Spring Boot框架版本
  • ${spring-boot.formatted-version} 格式化的Spring Boot框架版本,前缀是v
  • ${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME})
    给文字加颜色,加背景,加样式,NAME的值可以在这里获取ansi
  • ${application.title} 应用程序的标题

如图我给banner 加上了颜色,加上了版本

在这里插入图片描述
配置如下:

${AnsiColor.GREEN}
  /$$$$$$   /$$$$$$  /$$$$$$$  /$$   /$$       /$$$$$$ /$$$$$$$$ /$$$$$$   /$$$$$$  /$$     /$$ /$$$$$$   /$$$$$$  /$$     /$$
 /$$__  $$ /$$__  $$| $$__  $$| $$$ | $$      |_  $$_/|__  $$__//$$__  $$ /$$__  $$|  $$   /$$//$$__  $$ /$$__  $$|  $$   /$$/
| $$  \__/| $$  \__/| $$  \ $$| $$$$| $$        | $$     | $$  | $$  \__/| $$  \ $$ \  $$ /$$/| $$  \__/| $$  \ $$ \  $$ /$$/
| $$      |  $$$$$$ | $$  | $$| $$ $$ $$ /$$$$$$| $$     | $$  |  $$$$$$ | $$$$$$$$  \  $$$$/ |  $$$$$$ | $$$$$$$$  \  $$$$/
| $$       \____  $$| $$  | $$| $$  $$$$|______/| $$     | $$   \____  $$| $$__  $$   \  $$/   \____  $$| $$__  $$   \  $$/
| $$    $$ /$$  \ $$| $$  | $$| $$\  $$$        | $$     | $$   /$$  \ $$| $$  | $$    | $$    /$$  \ $$| $$  | $$    | $$
|  $$$$$$/|  $$$$$$/| $$$$$$$/| $$ \  $$       /$$$$$$   | $$  |  $$$$$$/| $$  | $$    | $$   |  $$$$$$/| $$  | $$    | $$
 \______/  \______/ |_______/ |__/  \__/      |______/   |__/   \______/ |__/  |__/    |__/    \______/ |__/  |__/    |__/
${AnsiColor.DEFAULT}
::Spring Boot Version: ${AnsiColor.RED}${spring-boot.formatted-version}${AnsiColor.DEFAULT}
::Application Version: ${AnsiColor.RED}${application.formatted-version}${AnsiColor.DEFAULT}

  • 如果颜色不起作用,那就是需要开启一下:spring.output.ansi.enabled=always
  • ${AnsiColor.DEFAULT} 是将颜色重置,防止前面的颜色影响下面的
  • ${application.formatted-version} 、 ${application.version}、 ${application.title} 要使用jar包启动才会打印
  • banner.txt 中可以配置环境变量environment中的任何键值

使用图片做banner

在Spring Boot 3.x版本中已经不被支持

编码方式定义banner

自定义一个CustomBanner类,实现Banner接口,如:

import org.springframework.boot.Banner;
import org.springframework.core.env.Environment;

import java.io.PrintStream;

public class CustomBanner implements Banner {

    public static final String BANNER = "  /$$$$$$   /$$$$$$  /$$$$$$$  /$$   /$$       /$$$$$$ /$$$$$$$$ /$$$$$$   /$$$$$$  /$$     /$$ /$$$$$$   /$$$$$$  /$$     /$$\n" +
            " /$$__  $$ /$$__  $$| $$__  $$| $$$ | $$      |_  $$_/|__  $$__//$$__  $$ /$$__  $$|  $$   /$$//$$__  $$ /$$__  $$|  $$   /$$/\n" +
            "| $$  \\__/| $$  \\__/| $$  \\ $$| $$$$| $$        | $$     | $$  | $$  \\__/| $$  \\ $$ \\  $$ /$$/| $$  \\__/| $$  \\ $$ \\  $$ /$$/ \n" +
            "| $$      |  $$$$$$ | $$  | $$| $$ $$ $$ /$$$$$$| $$     | $$  |  $$$$$$ | $$$$$$$$  \\  $$$$/ |  $$$$$$ | $$$$$$$$  \\  $$$$/  \n" +
            "| $$       \\____  $$| $$  | $$| $$  $$$$|______/| $$     | $$   \\____  $$| $$__  $$   \\  $$/   \\____  $$| $$__  $$   \\  $$/   \n" +
            "| $$    $$ /$$  \\ $$| $$  | $$| $$\\  $$$        | $$     | $$   /$$  \\ $$| $$  | $$    | $$    /$$  \\ $$| $$  | $$    | $$    \n" +
            "|  $$$$$$/|  $$$$$$/| $$$$$$$/| $$ \\  $$       /$$$$$$   | $$  |  $$$$$$/| $$  | $$    | $$   |  $$$$$$/| $$  | $$    | $$    \n" +
            " \\______/  \\______/ |_______/ |__/  \\__/      |______/   |__/   \\______/ |__/  |__/    |__/    \\______/ |__/  |__/    |__/    \n";

    @Override
    public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
        printStream.println(BANNER);
    }
}

SpringApplication 中配置banner

SpringApplication springApplication = new SpringApplication(SpringBootDemoApplication.class);
springApplication.setBanner(new CustomBanner());

如果在类路径中存在banner.txt 在会优先使用banner.txt

禁用banner

Spring Boot 提供了spring.main.banner-mode 配置,OFF-关闭banner打印,CONSOLE-使用System.out打印banner,log文件不会记录,LOG-打印到log文件

另外同样可以用springApplication.setBannerMode(Banner.Mode.OFF);方式设置banner

加载打印原理

在之前的《Spring Boot 框架整体启动流程详解》中,我们看到有一步是

//打印banner
Banner printedBanner = printBanner(environment);

这一步就是加载打印banner的核心。

private Banner printBanner(ConfigurableEnvironment environment) {
//如果bannerMode是关闭的,就会不打印banner
	if (this.bannerMode == Banner.Mode.OFF) {
		return null;
	}
	//获取资源加载器,如果当前没有就使用默认的资源加载器
	ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
			: new DefaultResourceLoader(null);
//创建一个SpringBoot应用程序的banner打印类,如果通过setBanner设置,this.banner会有值
	SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
	//如果bannerMode 是打印到log文件
	if (this.bannerMode == Mode.LOG) {
		return bannerPrinter.print(environment, this.mainApplicationClass, logger);
	}
	//默认打印到控制台
	return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}

先看下如何打印到log文件:

Banner print(Environment environment, Class<?> sourceClass, Log logger) {
//获取Banner对象
	Banner banner = getBanner(environment);
	try {
	//使用log 的info 级别打印
		logger.info(createStringFromBanner(banner, environment, sourceClass));
	}
	catch (UnsupportedEncodingException ex) {
		logger.warn("Failed to create String for banner", ex);
	}
	//创建一个打印banner的装饰器bean,允许后期再次使用
	return new PrintedBanner(banner, sourceClass);
}

如何获取的Banner对象:

private Banner getBanner(Environment environment) {
//获取txt文本banner
	Banner textBanner = getTextBanner(environment);
	if (textBanner != null) {
		return textBanner;
	}
	//fallbackBanner 为前期通过setBanner设置的自定义banner
	//可见如果两者同时设置,优先使用的txt文本banner
	if (this.fallbackBanner != null) {
		return this.fallbackBanner;
	}
	//都没有,返回一个默认的SpringBootBanner
	return DEFAULT_BANNER;
}

如果获取txt文本banner:

private Banner getTextBanner(Environment environment) {
//从环境变量中获取spring.banner.location指定的banner地址,如果没有,使用banner.txt
	String location = environment.getProperty(BANNER_LOCATION_PROPERTY, DEFAULT_BANNER_LOCATION);
	//获取指定的资源对象
	Resource resource = this.resourceLoader.getResource(location);
	try {
	//资源存在,并且资源路径中不包含liquibase-core
		if (resource.exists() && !resource.getURL().toExternalForm().contains("liquibase-core")) {
		//创建一个从源打印的banner对象,实现了Banner接口
			return new ResourceBanner(resource);
		}
	}
	catch (IOException ex) {
		// Ignore
	}
	return null;
}

获取到文本banner的ResourceBanner资源对象后,回到print(Environment environment, Class<?> sourceClass, Log logger) 这个方法中,接下来就是要把获取到banner对象打印出来,createStringFromBanner将获取到banner对象,调用其中的printBanner方法,把输出流转为UTF-8的字符串输出到log文件中。

private String createStringFromBanner(Banner banner, Environment environment, Class<?> mainApplicationClass)
		throws UnsupportedEncodingException {
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	banner.printBanner(environment, mainApplicationClass, new PrintStream(baos));
	String charset = environment.getProperty("spring.banner.charset", "UTF-8");
	return baos.toString(charset);
}

ResourceBanner的printBanner方法:

public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
	try {
	//从流读取banner.txt 字符串,使用spring.banner.charset编码,或者UTF-8
		String banner = StreamUtils.copyToString(this.resource.getInputStream(),
				environment.getProperty("spring.banner.charset", Charset.class, StandardCharsets.UTF_8));
				//获取用于解析占位符的所有属性源
		for (PropertyResolver resolver : getPropertyResolvers(environment, sourceClass)) {
		//解析banner,使用PropertyPlaceholderHelper工具类解析
			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);
	}
}

bannerPrinter.print(environment, this.mainApplicationClass, System.out);
打印到控制台的逻辑也是一样的,只是直接输出到控制台

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

总结

通过图来总结一下整个流程
在这里插入图片描述

作者其他要推荐的文章,欢迎来学习:
Prometheus 系列文章

  1. Prometheus 的介绍和安装
  2. 直观感受PromQL及其数据类型
  3. PromQL之选择器和运算符
  4. PromQL之函数
  5. Prometheus 告警机制介绍及命令解读
  6. Prometheus 告警模块配置深度解析
  7. Prometheus 配置身份认证
  8. Prometheus 动态拉取监控服务
  9. Prometheus 监控云Mysql和自建Mysql

Grafana 系列文章,版本:OOS v9.3.1

  1. Grafana 的介绍和安装
  2. Grafana监控大屏配置参数介绍(一)
  3. Grafana监控大屏配置参数介绍(二)
  4. Grafana监控大屏可视化图表
  5. Grafana 查询数据和转换数据
  6. Grafana 告警模块介绍
  7. Grafana 告警接入飞书通知

Spring Boot Admin 系列

  1. Spring Boot Admin 参考指南
  2. SpringBoot Admin服务离线、不显示健康信息的问题
  3. Spring Boot Admin2 @EnableAdminServer的加载
  4. Spring Boot Admin2 AdminServerAutoConfiguration详解
  5. Spring Boot Admin2 实例状态监控详解
  6. Spring Boot Admin2 自定义JVM监控通知
  7. Spring Boot Admin2 自定义异常监控
  8. Spring Boot Admin 监控指标接入Grafana可视化

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

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

相关文章

快速排序算法的编码和优化

快速排序的基本思路是&#xff1a; 先通过第一趟排序&#xff0c;将数组原地划分为两部分&#xff0c;其中一部分的所有数据都小于另一部分的所有数据。原数组被划分为2份通过递归的处理&#xff0c; 再对原数组分割的两部分分别划分为两部分&#xff0c;同样是使得其中一部分…

springboot+java高校教材征订管理系统

教材管理系统从功能、数据流程、可行性、运行环境等方面进行需求分析。对教材管理系统的数据库、功能进行了详细设计。分析了主要界面设计和相关组件设计&#xff0c;对教材管理系统的具体实现进行了介绍。 采用Java技术&#xff0c;从数据库中获取数据、向数据库中写入数据&am…

Linux 4.10 将带来深远影响的三项小改变

Linux的演进永不停歇。Linus Torvalds一直在努力工作&#xff0c;希望能够在新的内核版本当中(4.11)融入更多变化。不过在目前的Linux 4.10中&#xff0c;我们同样发现了三组能够有效提升性能并实现多种前所未有功能集的变更。 Linux的演进永不停歇。Linus Torvalds一直在努力…

如何快速写出一个完整的测试用例

一、前言 测试工作中最为基础核心的内容就是设计测试用例&#xff0c;我们一般会认为数量越少、发现缺陷越多的用例就是好的用例。那么&#xff0c;怎样才能设计出好的测试用例呢&#xff1f;本次专题就向大家介绍如何编写一个完整且靠谱的测试用例。 二、测试用例的重要性 …

使用IPSW文件将iOS系统从Beta恢复到稳定正式版教程

起因 作为一名iOS开发者&#xff0c;为了拥抱新系统&#xff08;手贱&#xff09;&#xff0c;将开发机升级到了最新的iOS 17 Beta版本&#xff0c;从而导致使用现有的Xcode无法成功配对该版本系统。故准备想方设法回滚到原先的iOS 16.5稳定版 回滚方式 若要将iOS设备回退至…

【MySQL高级篇笔记-数据库其它调优策略(中) 】

此笔记为尚硅谷MySQL高级篇部分内容 目录 一、数据库调优的措施 1、调优的目标 2、如何定位调优问题 3、调优的维度和步骤 二、优化MySQL服务器 1、优化服务器硬件 2、优化MySQL的参数 三、优化数据库结构 1、拆分表&#xff1a;冷热数据分离 2、增加中间表 3、增加…

CKA 01_docker部署Kubernetes 部署docker 使用kubeadm引导集群 安装Pod网络

文章目录 1. 虚拟机步骤2. Docker 部署 Kubernetes2.1 部署 docker2.1.1 环境要求2.1.2 安装 docker 引擎2.1.3 worker 节点对 master 节点免密2.1.4 设定 docker 开机自启2.1.5 打开桥接&#xff0c;查看桥接流量2.1.6 设定 systemd 方式管理 cgroup2.1.7 docker部署完成2.1.8…

光伏储能直流系统MATLAB仿真(PV光伏阵列+Boost DCDC变换器+负载+双向DCDC变换器+锂离子电池系统)

PV光伏阵列Boost DCDC变换器负载双向DCDC变换器锂离子电池系统 资源地址&#xff1a; 光伏储能直流系统MATLAB仿真&#xff08;PV光伏阵列BoostDCDC变换器负载双向DCDC变换器锂离子电池系统&#xff09;-Matlab文档类资源-CSDN文库 主要模块&#xff1a; PV光伏阵列、Boost…

这 3个Python 函数你知道吗?

动动发财的小手&#xff0c;点个赞吧&#xff01; 作为21世纪最流行的语言之一&#xff0c;Python当然有很多有趣的功能值得深入探索和研究。今天将介绍其中的三个&#xff0c;每个都从理论上和通过实际示例进行介绍。 我想要介绍这些函数的主要原因是它们可以帮助您避免编写循…

CKA 09_Kubernetes工作负载与调度 资源调度 三类QoS request 资源需求 limit 资源限额

文章目录 1. 资源调度1.1 准备工作1.2 为什么需要 request 和 limit1.3 内存限制1.3.1 Brustable1.3.2 Guaranteed1.3.3 BestEffort1.3.4 当容器申请的资源超出 limit 和 request 1.4 CPU限制 1. 资源调度 1.1 准备工作 Kubernetes 采用 request 和 limit 两种限制类型来对资源…

中国电子学会2023年05月份青少年软件编程Python等级考试试卷一级真题(含答案)

2023-05 Python一级真题 分数&#xff1a;100 题数&#xff1a;37 测试时长&#xff1a;60min 一、单选题(共25题&#xff0c;共50分) 1. 可以对Python代码进行多行注释的是&#xff1f;&#xff08;C &#xff09; A.# B." " C. D. 2. 下列可以作为Py…

ChatGPT有哪些神奇的使用方式? ChatGPT十大功能

原文&#xff1a;ChatGPT有哪些神奇的使用方式? ChatGPT十大功能_其他工具_软件教程_脚本之家 随着微软、百度等巨头加码&#xff0c;AIGC&#xff08;人工智能自动生成内容&#xff09;领域或将成为2023年最值得关注的、全球最热门赛道。AI大模型相当于是通过积累大量知识&a…

MT6705B 同步整流器

MT6705B 是用于反激式变换器的高性能45V 同步整流器。它兼容各种反激转换器类型。支持 DCM、CCM 和准谐振模式。MT6705B集成了一个40V功率MOSFET&#xff0c;可以取代肖特基二极管&#xff0c;提高效率。V SW <V TH-ON 时&#xff0c;内部 MOSFET 导通。V SW >V TH-OFF 时…

前端响应式布局--更新中

前端响应式布局原理与方案&#xff08;详细版&#xff09; 文章目录 媒体查询Grid布局Flex布局 响应式布局&#xff1a;在不同屏幕尺寸下&#xff0c; 同一页面有不同的布局。 传统的开发模式&#xff1a;PC端搞一套布局&#xff0c;移动端搞一套布局。 使用了响应式布局&#…

SpringBoot中集成Swagger2

介绍 Swagger是非常流行的API框架&#xff0c;能够自动生成RESTFul 风格的API文档&#xff0c;还可以在线测试后台接口。 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息&#xff0c;再通过Swagger衍生出来的一系列项目和工具&#xff0c;就可以做到生成各种格式…

【论文阅读】Language Models are Few-Shot Learners(GPT-3)

前言 本文简要介绍了GPT-3的背景&#xff0c;模型架构&#xff0c;训练数据以及训练方式部分。具体训练细节&#xff0c;实验结果很多&#xff0c;可以在用到的时候再看 Intro 本文剖析了pretrain-finetune架构存在的问题&#xff1a; 对于每个新的任务&#xff0c;都需要大…

kotlin withTimeoutOrNull超时返回

kotlin withTimeoutOrNull超时返回 import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withTimeoutOrNullfun main(args: Array<String>) {testTimeOut(1000) //如果是2000&#xff0c;则正常返回 OK }fun testTimeOut(…

OpenGL 坐标系统

1.简介 OpenGL希望在每次顶点着色器运行后&#xff0c;我们可见的所有顶点都为标准化设备坐标。也就是说&#xff0c;每个顶点的x&#xff0c;y&#xff0c;z坐标都应该在-1.0到1.0之间&#xff0c;超出这个坐标范围的顶点都将不可见。将坐标变换为标准化设备坐标&#xff0c;接…

在职读研探索更大的世界,中国人民大学与加拿大女王大学金融硕士给予你前行的力量

生活总是在变化中前进&#xff0c;这个世界从未停止过为我们带来新的挑战和机遇。职场中我们偶尔会感到困惑和迷茫&#xff0c;不知道该怎么去做。但我们可以选择去发现更大的世界&#xff0c;重新定义自己。中国人民大学与加拿大女王大学金融硕士项目给予你前行的力量。 知识…

建站教程:阿里云服务器安装宝塔面板搭建网站全流程

使用阿里云服务器安装宝塔面板教程&#xff0c;阿里云服务器网以CentOS操作系统为例&#xff0c;安装宝塔Linux面板&#xff0c;先远程连接到云服务器&#xff0c;然后执行宝塔面板安装命令&#xff0c;系统会自动安装宝塔面板&#xff0c;安装完成后会返回面板地址、账号和密码…