SpringBoot趣探究--1.logo是如何打印出来的

news2024/11/18 10:24:34

一.前言

 从本篇开始,我将对springboot框架做一个有趣的探究,探究一下它的流程,虽然源码看不懂,不过我们可以一点一点慢慢深挖,好了,下面我们来看一下本篇的知识,这个logo是如何打印出来的?

二.分析

  springboot在启动的时候会打印一个spring的logo以及对应的版本等信息,下面我们看一下这个是如何打印的?

 我们先新建一个springboot空项目,然后我们先看一下启动类:

很平常的一个启动类,那么他是如何打印的呢?看到这里有个run方法,既然run方法能启动项目,那么run方法里面肯定调用了main()方法,我们点进去看一下这个SpringApplication类:

 

好家伙,这么多属性,别急,我们先先看一下,我们发现他第一个属性是个字符串叫banner.txt,这时我突然想到之前学修改springboot启动Logo时,只需要在resoures目录下创建一个banner.txt文件,然后写入我们的Logo,那么它就会变成我们的logo,是不是这样呢?我们先试一下:

在resources目录下创建banner.txt文件,然后写入:

 

随便一个文字型的logo,然后我们启动项目:

 

看到了我们的springlogo变成了我们自己的logo,好,那么为什么默认是spring的logo呢?

继续看一下,有哪些方法或者属性:

 

  我们发现这个类中还有一个Banner类的成员变量,我们点进去看一下:

 

@FunctionalInterface
public interface Banner {
    void printBanner(Environment environment, Class<?> sourceClass, PrintStream out);

    public static enum Mode {
        OFF,
        CONSOLE,
        LOG;

        private Mode() {
        }
    }
}

发现它是一个接口,有一个默认的printBanner方法,不过既然是接口,那么我们需要去找它的实现类,我们看一下它有哪些实现类?

可以看到,它有五个实现类,还有ImageBanner这个,这个应该是打印图片Logo的,还有 

我们看他最后一个SpringBootBanner类,点进去看一下:

 

class SpringBootBanner implements Banner {
    private static final String[] BANNER = new String[]{"", "  .   ____          _            __ _ _", " /\\\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\", "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\", " \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )", "  '  |____| .__|_| |_|_| |_\\__, | / / / /", " =========|_|==============|___/=/_/_/_/"};
    private static final String SPRING_BOOT = " :: Spring Boot :: ";
    private static final int STRAP_LINE_SIZE = 42;

    SpringBootBanner() {
    }

    public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
        String[] var4 = BANNER;
        int var5 = var4.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String line = var4[var6];
            printStream.println(line);
        }

        String version = SpringBootVersion.getVersion();
        version = version != null ? " (v" + version + ")" : "";
        StringBuilder padding = new StringBuilder();

        while(padding.length() < 42 - (version.length() + " :: Spring Boot :: ".length())) {
            padding.append(" ");
        }

        printStream.println(AnsiOutput.toString(new Object[]{AnsiColor.GREEN, " :: Spring Boot :: ", AnsiColor.DEFAULT, padding.toString(), AnsiStyle.FAINT, version}));
        printStream.println();
    }
}

我们发现,它有一个final的String数组,里面有一些字符,然后它的printBanner方法里面的while循环里面还有好像是打印::Spring Boot::的代码,现在我们可以确定,它是吧图标写在数组里面的,然后直接打印这个数组了,不信的话,吧这个类单独拿出来,测试一下:

@SpringBootTest
class StudyAutoConfigurationApplicationTests {

    private static final String[] BANNER = new String[]{"", "  .   ____          _            __ _ _", " /\\\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\", "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\", " \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )", "  '  |____| .__|_| |_|_| |_\\__, | / / / /", " =========|_|==============|___/=/_/_/_/"};
    private static final String SPRING_BOOT = " :: Spring Boot :: ";
    private static final int STRAP_LINE_SIZE = 42;


    @Test
    void contextLoads() throws IOException {

        printBanner();
    }
        public void printBanner() throws IOException {

           // PrintStream printStream = new PrintStream(Files.newOutputStream(Paths.get("a.txt")));


            String[] var4 = BANNER;
            int var5 = var4.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String line = var4[var6];
                System.out.println(line);
            }

            String version = SpringBootVersion.getVersion();
            version = " (v" + version + ")";
            StringBuilder padding = new StringBuilder();

            while(padding.length() < 42 - (version.length() + " :: Spring Boot :: ".length())) {
                padding.append(" ");
            }

            System.out.println(AnsiOutput.toString(AnsiColor.GREEN, " :: Spring Boot :: ", AnsiColor.DEFAULT, padding.toString(), AnsiStyle.FAINT, version));
            System.out.println();
        }

}

我们在springboot的测试类中封装这些属性和方法,然后我们测试一下:

可以看到,成功的打印出来了logo,这样就解决了心中的疑惑, 

不过之前我们还看到有一个ImageBanner类,这个应该是打印图片的,我们先看一下:

public class ImageBanner implements Banner {
    private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
    private static final String PROPERTY_PREFIX = "spring.banner.image.";
    private static final Log logger = LogFactory.getLog(ImageBanner.class);
    private static final double[] RGB_WEIGHT = new double[]{0.2126, 0.7152, 0.0722};
    private final Resource image;

    public ImageBanner(Resource image) {
        Assert.notNull(image, "Image must not be null");
        Assert.isTrue(image.exists(), "Image must exist");
        this.image = image;
    }

 可以看到它好像需要一个java.awt.headless还有一个spring.banner.image.前缀的文件,看一下他的printBanner方法:


    public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
        try {
            if (System.getProperty("java.awt.headless") == null) {
                System.setProperty("java.awt.headless", "true");
            }

            this.printBanner(environment, out);
        } catch (Throwable var5) {
            logger.warn(LogMessage.format("Image banner not printable: %s (%s: '%s')", this.image, var5.getClass(), var5.getMessage()));
            logger.debug("Image banner printing failure", var5);
        }

    }

    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);
        AnsiColors.BitDepth bitDepth = this.getBitDepthProperty(environment);
        PixelMode pixelMode = this.getPixelModeProperty(environment);
        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());
        }

    }

 可以看到,读取了宽度,高度,margin,invert等属性,不过控制台应该没法演示,它应该是Java的图形化编程用的,awt

好了,以上就是对springboot的logo原理分析了,这也是作为springboot系列文章的开端,希望以后能带来更多好玩有趣的知识!

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

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

相关文章

2014年2月24日 Go生态洞察:FOSDEM 2014上的Go演讲精选

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

【Echart】Echart设置label太长隐藏:

文章目录 第一种&#xff1a;竖排显示第二种&#xff1a;显示部分第三种&#xff1a;强制显示所有标签并旋转 第一种&#xff1a;竖排显示 xAxis: {type: category,data: res.data.data.sz.xAxis,axisLabel:{fontSize:12,formatter: function(value) {return value.split().joi…

gitlab安装以及创建用户创建组,修改密码 邮箱配置 数据备份与恢复--保姆级教学!

GitLab是一种基于Web的Git仓库管理工具&#xff0c;它允许您在组织或个人级别上创建和管理Git仓库&#xff0c;以便在一个中心位置上执行代码管理和协作工作。GitLab提供了强大的功能&#xff0c;如代码审查、问题跟踪、CI/CD、容器注册表、Wiki和持续集成等。 以下是GitLab的…

gitlab安装配置及应用

安装 ##安装依赖 yum install -y curl policycoreutils-python openssh-server perl#上传包 rz gitlab-jh-16.5.2-jh.0.el7.x86_64.rpm 安装 yum install gitlab-jh-16.0.3-jh.0.el7.x86_64.rpm 初始化并启动 # 以下两种方法都可以配置访问地址&#xff0c;第一种需要在yum安…

2023年【A特种设备相关管理(锅炉压力容器压力管道)】模拟考试题及A特种设备相关管理(锅炉压力容器压力管道)作业考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 A特种设备相关管理&#xff08;锅炉压力容器压力管道&#xff09;模拟考试题参考答案及A特种设备相关管理&#xff08;锅炉压力容器压力管道&#xff09;考试试题解析是安全生产模拟考试一点通题库老师及A特种设备相关…

[Docker]八.Docker 容器跨主机通讯

一.跨主机通讯原理 在主机192.168.31.140上的docker0(172.17.0.0/16)中有一个容器mycentos( 172.17.0.2/16), 在主机192.168.31.81上的docker0(172.17.0.0/16)中有一个容器mycentos( 172.17.0.2/16),然后在主机192.168.31.140上ping主机192.168.31.81,发现ping不通要实现两个主…

【代数学习题4.1】从零理解范数与迹 —— 求极小多项式

从零理解范数与迹 —— 求极小多项式 写在前面概念解释题目解答 1. 极小多项式极小多项式的求法1. 对 α \alpha α 的极小多项式python求解 2. 对 α 1 \alpha 1 α1 的极小多项式python找到多项式python找到极小多项式 3. 对 α 2 α 1 \alpha^2 \alpha 1 α2α1 的…

高校档案室建设标准-高校数字档案室建设需考虑哪些因素

高校档案室是高等教育机构所建立的档案存放与管理的机构&#xff0c;主要负责高校行政、教学、科研、文化和保密等方面的档案的收集、整理、保存、利用和管理工作。高校档案室是高等教育机构的重要组成部分&#xff0c;旨在为高校的历史研究、管理和服务提供必要的档案资源。同…

STM32F4串口USART发送为00的解决方案

检查接线是否正确检查TX是否为复用推挽输出 3.检查是否将TX和RX引脚重映射为USART功能 在STM32中&#xff0c;每个GPIO引脚可以配置为不同的复用功能&#xff0c;例如UART、SPI、I2C等。具体来说&#xff0c;GPIO_PinAFConfig函数用于配置GPIO引脚的复用功能。它的参数包括GPIO…

Java使用x-www-form-urlencoded发请求

平常在开发过程中用的最多的就是JSON格式&#xff0c;请求编码就是 application/json&#xff0c;但偏偏有些接口是 x-www-form-urlencoded&#xff0c;怎么办呢&#xff0c;重新封装喽 在POSTMan工具是叫 x-www-form-urlencoded 在 APIpost工具中是叫 urlencoded Map<Str…

Monoxide relay机制和连弩挖矿

这篇文章就两个点&#xff0c;relay机制 、 连弩挖矿 relay 最终原子性 Eventual Atomicity 一笔跨链交易&#xff0c;从取款shard中发出&#xff0c;到存款shard中. 当收款shard中将这笔夸片交易打包上链后&#xff0c;原子性才执行结束。 这样做的延迟是比较小的。 如何应…

uniapp、微信小程序返回上页面刷新数据

目录 前言&#xff1a; 方法1&#xff1a; 方法2&#xff1a; 方法3&#xff1a; 前言&#xff1a; 返回上页面刷新数据这个功能主要用于在当前页面点击跳转到另一个页面之后&#xff0c;在另一个页面对数据进行了操作&#xff0c;比如&#xff1a;阅读量&#xff0c;然后返…

接入电商数据平台官方开放平台API接口获取商品实时信息数据,销量,评论,详情页演示

要接入电商数据平台官方开放平台API接口获取商品实时信息数据、销量、评论和详情页演示&#xff0c;需要按照以下步骤进行操作&#xff1a; 找到可用的API接口&#xff1a;首先&#xff0c;需要找到支持查询商品信息的API接口。可以在电商数据平台的官方开放平台上查找相应的AP…

react等效memo的方法

视频教程 前端技术&#xff5c;Dan博客&#xff5c;在你写memo()之前_哔哩哔哩_bilibili 把与ExpensiveTree的无关的dom做成一个组件 第二种情况&#xff0c;color在ExpensiveTree组件的父级dom 创建一个组件&#xff0c;将state的color和input写上&#xff0c;而ExpensiveTr…

【智能优化算法】从蚁群到动物园

目录 引言蚁群优化算法&#xff08;ACO&#xff09;ACO 机理ACO 模型描述ACO 移动策略 粒子群优化算法&#xff08;PSO&#xff09;PSO 机理PSO 模型描述 萤火虫群优化算法&#xff08;GSO&#xff09;GSO 机理GSO 模型描述 群智能优化算法 引言 21世纪&#xff0c;人类社会已经…

梯度引导的分子生成扩散模型- GaUDI 评测

GaUDI模型来自于以色列理工Tomer Weiss的2023年发表在预印本ChemRxiv上的工作 《Guided Diffusion for Inverse Molecular Design》。原文链接&#xff1a;Guided Diffusion for Inverse Molecular Design | Materials Chemistry | ChemRxiv | Cambridge Open Engage GaUDI模型…

问题 R: 胜利大逃亡(HUST)

#include <deque> #define inf 200000 #include<iostream> #include<queue> using namespace std;// 迷宫坐标 int map[59][59][59] { 0 };// 可访问标记 int visit[51][51][51] { 0 }; // 移动方式 int next1[7][4] { {1,0,0},{-1,0,0}, {0,1,0},{0,-1,…

超级实用的程序员接单平台,看完少走几年弯路,强推第一个!

”前途光明我看不见&#xff0c;道路曲折我走不完。“ 兜兜转转&#xff0c;心心念念&#xff0c;念念不忘&#xff0c;必有回响。终于找到了....... 网络上好多人都在推荐程序员线上接单&#xff0c;有人说赚得盆满钵满&#xff0c;有的人被坑得破口大骂&#xff0c;还有的人…

苍穹外卖—解决前端时间属性显示问题

项目场景&#xff1a; 点击员工管理 出现显示时间属性问题 输入员工姓名为zhangsan 现实的时间属性是数组类型 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 例如&#xff1a;数据传输过程中数据不时出现丢失的情况&#xff0c;偶尔会丢失一部分数据 APP …