我与framework的爱恨故事(面试篇)

我与framework的爱恨故事(面试篇)

我拿自己做实验

时间回到2022年8月, 当时为2023年4月跳槽(高级开发工程师)做准备,我是转行到程序员的行业,学历也比较的差。当时手里只有两张牌, 一是Rocketmq消息中间件源码,二是framework系统脚手架。再三思考后,我决定以自己作为实验,验证是否能用framework系统脚手架打开高级开发工程师的大门。于是用了几个月的时间, 结合公司的需求, 写了一整套framework系统框架, 并稳定在线上运行。4月份去面试时, 和面试官聊了近3小时, 这是我面试时间最长的一次, 当时就针对framework里的多个组件进行探讨, 那种感觉真的是太好了,有一种面试官是同道中人一般的错觉!

framework给了我什么

framework带给我的不仅仅是面试的成功, 薪资与职位的增长, 更多的是我收获了解决问题的思路!平常我们做业务功能开发,大家心里普遍会有一种感受:增删改查, 解决的是业务流程与逻辑的问题。在构建framework的过程中, 你会去思考,你会在心里给自己压力(这是整个系统依赖的基础框架,出不得半点问题),同时你写的代码得经得起大家的评审,设计实现得优雅(可不能被同事笑话了,哈哈)。更多的是解决一些成熟框架带来的技术问题!每次面对这样的技术问题, 从最开始的无从下手, 然后一点点debug框架源代码抓住我想要修改核心的东西,最后实现我想要的功能(一般此刻会打开手机音乐跟着哼),心里非常的爽,或许这就是作为程序员的快乐!

framework整合log4j2的一次快乐旅程

为什么最开始是日志框架, 因为我觉得, 事情都是慢慢按照线性进行的发展的, 首先把mvc简答引入到项目中, 请求已经可以进入到系统了, 那么就可以做简单的逻辑处理, 那你得打日志进行一些记录吧!这时候就灵魂三问自己了, 日志文件放在哪呢,方便以后进行统一的日志收集, 日志文件该什么样的格式呢 ,logout.log? 服务名.log? , 是不是得有一整套自己的日志模版?对对对, 都没有错, 那就开始解决这些问题!

日志文件放在哪,格式是什么? <math xmlns="http://www.w3.org/1998/Math/MathML"> s y s : u s e r . h o m e / l o g s / a p p / {sys:user.home}/logs/app/ </math>sys:user.home/logs/app/{FILE_NAME} , FILE_NAME是每一个服务应用的applicationName

下面是简单的日志文件配置, 主要关注sys:applicationName与sys:logLevel动态参数

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="0">
    <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->

    <!--变量配置-->
    <Properties>
        <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
        <!-- %logger{36} 表示 Logger 名字最长36个字符 -->
        <property name="LOG_PATTERN"
                  value="%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread]  %highlight{%p} %logger{36} - %msg%n"/>
        <property name="FILE_NAME" value="${sys:applicationName}"/>
        <!-- 定义日志存储的路径 -->
        <property name="FILE_PATH" value="${sys:user.home}/logs/app/${FILE_NAME}"/>
        <property name="LOG_LEVEL" value="${sys:logLevel}"/>

    </Properties>

    <appenders>

        <console name="Console" target="SYSTEM_OUT">
            <!--输出日志的格式-->
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="${LOG_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
        </console>

        <!-- 这个会打印出所有的info及以上级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFile" fileName="${FILE_PATH}/${FILE_NAME}.log"
                     filePattern="${FILE_PATH}/${FILE_NAME}-%d{yyyy-MM-dd}_%i.log.gz">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="${LOG_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,默认是1 hour-->
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="100MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>
    </appenders>

    <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
    <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
        <root level="${LOG_LEVEL}">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFile"/>
        </root>
    </loggers>

</configuration>

一阵引入启动, 发现效果不是自己想要的, 怎么没有加载我的日志配置文件,心里难受一秒钟, 问题不大!

发现几个问题:

  • 如何让springboot启动时 ,选择log4j2作为系统的日志文件(√)
  • 如何让springboot启动时, 加载我们自己的配置文件, 而不是默认的配置文件(√)
  • 加载配置文件的时候, 如果将sys:applicationName与sys:logLevel参数读取(√)

这时候, 就是一阵捣鼓,gpt ,google, 百度, 发现都不是我想要的, 但也有一点收获!这个时候脑瓜子里不觉间有一个想法, 既然springboot在启动时, 可以选择logback作为默认的日志框架,那肯定是有一个配置项的, 嘿嘿,顺着这个思路,果然被我发现了!告诉springboot在初始化时,LoggingSystem用Log4J2LoggingSystem就行了

java 复制代码
    private static final String LOGGING_SYSTEM_NAME = "org.springframework.boot.logging.LoggingSystem";
    private static final String LOG4J2_SYSTEM_NAME = "org.springframework.boot.logging.log4j2.Log4J2LoggingSystem";

    @Override
    public void onApplicationEvent(ApplicationStartingEvent event) {
        System.setProperty(LOGGING_SYSTEM_NAME, LOG4J2_SYSTEM_NAME);
    }

同理可得, 既然你可以加载默认的配置文件, 那么是否有一个配置, 同样的效果, 果然,又找到了,都是一样的套路!

java 复制代码
    private static final String LOG_CONFIG = "logging.config";
    private static final String CONFIG_LOCATION = "classpath:fd-log4j2.xml";
    System.setProperty(LOG_CONFIG, CONFIG_LOCATION);

对于动态的参数获取就比较的简单了,springboot在启动时, 通过ApplicationListener监听获取环境变量, 将对应的值复制到系统环境变量中即可, 心里非常舒服!

很自然打开了手机放起了音乐, 跟着哼起来!

最后

现在是2023年12月26日 0:23:40秒, 写这篇文章的时候总是不觉的嘴角上扬, 也希望读到文章的你也能获得一丢丢的乐趣! 献上整个框架代码地址:fd-framework: 企业级脚手架 (gitee.com),目前正在重写整个代码,一点点来, 很快就写完的!

相关推荐
m0_5719575829 分钟前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
测开小菜鸟4 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
P.H. Infinity5 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天5 小时前
java的threadlocal为何内存泄漏
java
caridle5 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^5 小时前
数据库连接池的创建
java·开发语言·数据库
苹果醋35 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx