java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java日志框架

Java手写一个日志框架的示例代码

作者:乐乐家的乐乐

日志框架是一种用于记录和管理应用程序运行时信息的软件组件,它通常提供了一套API让开发人员能够在代码中插入日志语句,下面我们就来学习一下如何手写一个日志框架吧

什么是日志框架

日志框架是一种用于记录和管理应用程序运行时信息的软件组件。它通常提供了一套API(Application Programming Interface),让开发人员能够在代码中插入日志语句,以便在应用程序运行时生成有关其状态和执行流的信息。

一个优秀的日志框架应该具备的功能:

常见的Java日志框架包括 Log4j、Logback、java.util.logging 等。

手写一个简单的日志框架应该怎么做

首先,我们需要明确我们要做的功能。

从日渐成熟的日志框架中,我们总计日志框架的核心功能有;

我写了一个简单的源码

import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * LeLog类用于记录不同日志级别的消息。
 */
public class LeLog {
    /**
     * 日志级别的枚举: INFO, WARN, ERROR
     */
    public enum LogLevel {
        INFO, WARN, ERROR
    }

    private static Class<?> defaultClass; // 用于日志记录的默认类
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); // 日志记录的日期格式
    private static Map<Class<?>, LeLog> instances = new HashMap<>(); // 存储LeLog实例的映射
    private Class<?> clazz; // 与日志关联的类

    /**
     * 构造函数,设置默认日志记录的类。
     * @param clazz 与日志关联的类
     */
    public LeLog(Class<?> clazz) {
        this.clazz = clazz;
        defaultClass = clazz; // 设置默认日志记录的类
    }

    /**
     * 多例模式创建实例
     * @param clazz 类
     * @return LeLog实例
     */
    public static synchronized LeLog getLeLog(Class<?> clazz) {
        if (!instances.containsKey(clazz)) {
            LeLog instance = new LeLog(clazz);
            instances.put(clazz, instance);
        }
        return instances.get(clazz);
    }

    /**
     * 将日志消息写入控制台和文件。
     * @param level 日志级别
     * @param logName 日志名称
     * @param message 日志消息
     */
    private static void write(LogLevel level, String logName, String message) {
        // 创建并格式化日志消息
        String timeStamp = dateFormat.format(new Date());
        String threadName = Thread.currentThread().getName();
        long threadId = Thread.currentThread().getId();
        String logMessage = timeStamp + " [" + level + "] "
                + "Thread: " + threadName + " (ID: " + threadId + ") "
                + logName + " - " + message;
        // 输出日志消息到控制台
        System.out.println(logMessage);
        // 将日志消息写入文件
        writeToFile(logMessage);
    }

    /**
     * 获取日志文件路径。
     * @return 日志文件路径
     */
    private static String getLogFile() {
        Properties prop = new Properties();
        try (FileInputStream input = new FileInputStream("le.log.properties")) {
            prop.load(input);
            String logFilePath = prop.getProperty("logFilePath");

            File logFolder = new File(logFilePath);
            if (!logFolder.exists()) {
                logFolder.mkdirs();
            }

            String logFileName = prop.getProperty("logFileName");
            return logFilePath + "/" + logFileName + "_" + LocalDate.now() + ".log";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将日志消息写入文件。
     * @param message 日志消息
     */
    private static void writeToFile(String message) {
        String logFile = getLogFile();
        if (logFile != null) {
            try (PrintWriter out = new PrintWriter(new FileWriter(logFile, true))) {
                out.println(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 记录INFO级别的日志消息。
     * @param message 日志消息
     */
    public static void info(String message){
        write(LeLog.LogLevel.INFO,defaultClass.getName(),message);
    }

    /**
     * 记录WARN级别的日志消息。
     * @param message 日志消息
     */
    public static void warn(String message){
        write(LogLevel.WARN,defaultClass.getName(),message);
    }

    /**
     * 记录ERROR级别的日志消息。
     * @param message 日志消息
     */
    public static void error(String message){
        write(LogLevel.ERROR,defaultClass.getName(),message);
    }

}

代码结构和核心思路

LeLog 类是一个用于记录不同日志级别消息的工具类。以下是它的核心思路和代码结构:

日志级别枚举: LeLog 定义了一个LogLevel枚举,包括 INFO、WARN 和 ERROR 三个级别,分别表示信息、警告和错误。

    /**
     * 日志级别的枚举: INFO, WARN, ERROR
     */
    public enum LogLevel {
        INFO, WARN, ERROR
    }

类与实例关联: LeLog 通过多例模式创建实例,每个实例与一个特定的类关联。这种设计使得每个类都有自己的日志记录器,方便了解来自不同类的日志信息。

    private static Map<Class<?>, LeLog> instances = new HashMap<>(); // 存储LeLog实例的映射
    private Class<?> clazz; // 与日志关联的类

    /**
     * 构造函数,设置默认日志记录的类。
     * @param clazz 与日志关联的类
     */
    public LeLog(Class<?> clazz) {
        this.clazz = clazz;
        defaultClass = clazz; // 设置默认日志记录的类
    }

    /**
     * 多例模式创建实例
     * @param clazz 类
     * @return LeLog实例
     */
    public static synchronized LeLog getLeLog(Class<?> clazz) {
        if (!instances.containsKey(clazz)) {
            LeLog instance = new LeLog(clazz);
            instances.put(clazz, instance);
        }
        return instances.get(clazz);
    }

日志消息格式化: 在 write 方法中,使用 SimpleDateFormat 对日期进行格式化,同时获取线程信息和日志级别,将这些信息拼接成格式化的日志消息。

    /**
     * 将日志消息写入控制台和文件。
     * @param level 日志级别
     * @param logName 日志名称
     * @param message 日志消息
     */
    private static void write(LogLevel level, String logName, String message) {
        // 创建并格式化日志消息
        String timeStamp = dateFormat.format(new Date());
        String threadName = Thread.currentThread().getName();
        long threadId = Thread.currentThread().getId();
        String logMessage = timeStamp + " [" + level + "] "
                + "Thread: " + threadName + " (ID: " + threadId + ") "
                + logName + " - " + message;
        // 输出日志消息到控制台
        System.out.println(logMessage);
        // 将日志消息写入文件
        writeToFile(logMessage);
    }

输出到控制台和文件: LeLog 将日志消息输出到控制台,并通过 writeToFile 方法将消息写入到文件。日志文件路径和文件名从配置文件中读取,提高了灵活性。日志文件名中包含当前日期,每天生成一个新的日志文件,方便按日期查看日志。

# 日志输出路径
logFilePath=logs/xxx/xx
# 日志输出名称
logFileName=xia_le
    /**
     * 获取日志文件路径。
     * @return 日志文件路径
     */
    private static String getLogFile() {
        Properties prop = new Properties();
        try (FileInputStream input = new FileInputStream("le.log.properties")) {
            prop.load(input);
            String logFilePath = prop.getProperty("logFilePath");

            File logFolder = new File(logFilePath);
            if (!logFolder.exists()) {
                logFolder.mkdirs();
            }

            String logFileName = prop.getProperty("logFileName");
            return logFilePath + "/" + logFileName + "_" + LocalDate.now() + ".log";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将日志消息写入文件。
     * @param message 日志消息
     */
    private static void writeToFile(String message) {
        String logFile = getLogFile();
        if (logFile != null) {
            try (PrintWriter out = new PrintWriter(new FileWriter(logFile, true))) {
                out.println(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

使用方法

使用 LeLog 记录日志非常简单。首先,通过 LeLog.getLeLog(Class clazz) 方法获取 LeLog 实例,然后通过该实例的 infowarnerror 方法记录不同级别的日志消息。以下是一个简单的示例:

public class TestOne {
    private static final LeLog leLog = LeLog.getLeLog(TestOne.class);
    public void test(){
        leLog.info("This is an information message.");
        leLog.warn("This is a warning message.");
        leLog.error("This is an error message.");
    }
}

public class TestTwo {
    private static final LeLog leLog = LeLog.getLeLog(TestTwo.class);
    public void test(){
        leLog.info("This is an information message.");
        leLog.warn("This is a warning message.");
        leLog.error("This is an error message.");
    }
}

public class Main {
    public static void main(String[] args) {
        new TestOne().test();
        new TestTwo().test();
    }
}

控制台输出如下

文件输出如下:

后期优化

这个类可以说是漏洞百出,我写出来不过是给大伙提供一个思路和一个敢于手写框架造轮子的程序员桀骜不驯的心。

那这个类来说,值得喷的点有哪些:

以上就是Java手写一个日志框架的示例代码的详细内容,更多关于Java日志框架的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文