`

仿log4j定制自己的Log工具类

 
阅读更多

原由:

log4j是很强大,可每次使用还要加入log4j包,还要使用配置文件。对于一般的小工具或小项目感觉还是有点大动作了。而且在使用log4j时每次还要每取个实例再传个参数来记录,感觉有点麻烦。就自己仿log4j使用jdk logger定制了一个自己的记录工具类。

 

工具类特点:

  • 无配置文件,默认为info级别,控制台输出,无需改动即可满足一般开发需要。。
  • 直接打log,在java文件中直接使用 Log.info("test"); 即可,如果输出到文件,则自动按不同级别生成不同记录文件
  • 使用四个级别的log。分别为 Log.debug(""); Log.info(""); Log.warn(""); Log.error(""); 对于一般项目已经足够。
  • log输出方式有两种,控制台输出和文件输出。输出格式两者统一。文件输出时的文件路径可定制。默认为class文件夹下,名称格式为 等级_时间.log 如: INFO_2011-10-12.log

工具类的使用:
直接默认配置
   Log.debug("debug");
        Log.info("info");
        Log.info("info1");
        Log.warn("warn");
        Log.error("error");
        try {
            throw new Exception("exception");
        } catch (Exception e) {
            Log.error(e);
        }
 结果:
2012-03-02 16:25:03 NewClass.java(Line:19): [INFO] info
2012-03-02 16:25:03 NewClass.java(Line:20): [INFO] info1
2012-03-02 16:25:03 NewClass.java(Line:21): [WARN] warn
2012-03-02 16:25:03 NewClass.java(Line:22): [ERROR] error
2012-03-02 16:25:03 NewClass.java(Line:26): 
java.lang.Exception: exception
at com.dfhstudio.thoughtfly.util.NewClass.main(NewClass.java:24)

要想使用文件记录,要改点代码变量,看javadoc注释



费话不说,直接上代码
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.ConsoleHandler;
import java.util.logging.ErrorManager;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.StreamHandler;

/**
 *  <b>自定义LOG工具,丁风华</b>
 * <ul>
 * <b>特点</b>
 * <li>无配置文件,默认为info级别,控制台输出,无需改动即可满足一般开发需要。。</li>
 * <li>直接打log,在java文件中直接使用 <code>Log.info("test");</code> 即可,如果输出到文件,则自动按不同级别生成不同记录文件</li>
 * <li>使用四个级别的log。分别为 <code>Log.debug(""); Log.info(""); Log.warn(""); Log.error("");</code> 对于一般项目已经足够。</li>
 * <li>log输出方式有两种,控制台输出和文件输出。输出格式两者统一。文件输出时的文件路径可定制。默认为class文件夹下,名称格式为 等级_时间.log 如: INFO_2011-10-12.log</li>
 * </ul>
 * <ul>
 * <b>输出到文件使用方法</b><br>
 * 更改构造器方法中的数据. private Log()<br>
 * 1.设置输出级别: setLogLevel("info");<br>
 * 2.设置输出到文件: HANDLER_FILE = true;<br>
 * 3.设置设置文件保存路径: LOG_FILE_PATH = "D:\\log\\";<br>
 * 4.设置每个文件的最大值: FILE_SIZE = 2000000; // *** 每个文件最大2M <br>
 * 5.设置每天最多生成多少个文件数量: FILE_MAX = 10; // *** 每天最多生成10个文件,最多不可超过100<br>
 * 6.设置log文件后缀名: LOG_FILE_LASTNAME = ".log";
 * </ul>
 * <ul>
 * <b>更改记录内容的格式</b><br>
 * 可更改 dealInfoFormat 方法中的 formatMessage 变量值即可。
 * </ul>
 * 
 * @author DingFengHua
 */
public class Log {

    private Log() {
        setLogLevel("INFO");

        HANDLER_CONSOLE = true; // *** 控制台输出
        HANDLER_FILE = false; // *** 文件输出

        // *** 如果不想使用文件打LOG,即 HANDLER_FILE = false;,则不用关心以下数据
        // *** 自动创建路径文件夹
        if (HANDLER_FILE) {

            // *** 1. LOG文件夹在class文件夹目录下
            // LOG_FILE_PATH = new File(Log.class.getClassLoader().getResource(".").getFile()).toString() + "/log/";
            // *** 2. 如果是web项目,LOG文件夹在项目根目录下
            LOG_FILE_PATH = new File(Log.class.getClassLoader().getResource("/").getFile()).toString() + "/../../log/";

            FILE_SIZE = 2000000; // *** 每个文件最大2M
            FILE_MAX = 10; // *** 每天最多生成10个文件,最多不可超过100

            LOG_FILE_LASTNAME = ".log"; // *** 文件后缀名
        }
    }

    /*
     * 以下内容不必更改**********************************************************************************************************
     */
    /* ************************************************************************************************************************* */
    private String getLogFileName(String level) {
        String firtFileName = LOG_FILE_PATH + level + "_" + getDateFormat("yyyy-MM-dd", new Date()) + LOG_FILE_LASTNAME;
        return firtFileName;
    }

    /**
     * 从字符串转换为JDKLOG的LEVEL等级
     * 
     * @param strLevel 自定义的等级字符串
     * @return JDKLOG的等级
     */
    private Level getLogLevelFromString(String strLevel) {
        Level l = Level.INFO;

        if (LEVEL_DEBUG.equalsIgnoreCase(strLevel)) {
            l = Level.FINE;
        }

        if (LEVEL_WARN.equalsIgnoreCase(strLevel)) {
            l = Level.WARNING;
        }

        if (LEVEL_ERROR.equalsIgnoreCase(strLevel)) {
            l = Level.SEVERE;
        }

        return l;
    }

    /**
     * 低等级记录
     * 
     * @param info 记录信息
     */
    public static void debug(String info) {
        INSTANCE.log(LEVEL_DEBUG, "[" + LEVEL_DEBUG + "] " + info, null);
    }

    /**
     * 普通信息记录
     * 
     * @param info 记录信息
     */
    public static void info(String info) {
        INSTANCE.log(LEVEL_INFO, "[" + LEVEL_INFO + "] " + info, null);
    }

    /**
     * 警告信息记录
     * 
     * @param info 记录信息
     */
    public static void warn(String info) {
        INSTANCE.log(LEVEL_WARN, "[" + LEVEL_WARN + "] " + info, null);
    }

    /**
     * 错误信息记录
     * 
     * @param info 记录信息
     */
    public static void error(String info) {
        INSTANCE.log(LEVEL_ERROR, "[" + LEVEL_ERROR + "] " + info, null);
    }

    /**
     * 错误信息记录
     * 
     * @param info 异常
     */
    public static void error(Throwable info) {
        INSTANCE.log(LEVEL_ERROR, "", info);
    }

    /**
     * 处理记录信息
     * 
     * @param level 信息等级
     * @param info  信息内容
     * @param exception  异常信息
     */
    private void log(String level, String info, Throwable exception) {
        checkFileDate(level);
        Logger logger = Logger.getLogger(level);
        if (!logList.contains(level)) {
            logList.add(level);
            dealHander(logger);
            dealInfoFormat(logger);
        }
        logger.setLevel(logOutPutLevel);
        logger.log(getLogLevelFromString(level), info, exception);

    }

    /**
     * 内容格式化,默认内容格式为 时间 文件名(行数):[等级] 内容
     * 
     * @param logger JDK Log
     */
    private void dealInfoFormat(Logger logger) {
        logger.setUseParentHandlers(false);

        StackTraceElement[] stackTraceElement = Thread.currentThread().getStackTrace();

        final StackTraceElement element = stackTraceElement[stackTraceElement.length - 1];

        for (Handler handler : logger.getHandlers()) {
            handler.setFormatter(new Formatter() {

                @Override
                public String format(LogRecord record) {
                    StringBuilder formatMessage = new StringBuilder();
                    formatMessage.append(getDateFormat("yyyy-MM-dd HH:mm:ss", new Date()));
                    formatMessage.append(" ").append(element.getFileName()).append("(Line:")
                                    .append(element.getLineNumber()).append("):").append(" ")
                                    .append(record.getMessage()).append("\n");

                    if (record.getThrown() != null) {
                        try {
                            StringWriter sw = new StringWriter();
                            PrintWriter pw = new PrintWriter(sw);
                            record.getThrown().printStackTrace(pw);
                            pw.close();
                            formatMessage.append(sw.toString());
                        } catch (Exception ex) {
                        }
                    }

                    return formatMessage.toString();
                }
            });
        }

    }

    /**
     * 输出处理,控制台和文件,文件输出的文件名格式为 等级_yyyy-MM-dd.log 如果有多个文件,会在文件名后递增数字
     * 
     * @param logger jdk log
     */
    private void dealHander(Logger logger) {
        boolean alreadyHasConsole = false, alreadyHasFile = false;
        Handler[] handlers = logger.getHandlers();
        for (int i = 0; i < handlers.length; i++) {
            if (handlers[i] instanceof ConsoleHandler) {
                alreadyHasConsole = true;
            } else if (handlers[i] instanceof MyFileHandler) {
                alreadyHasFile = true;
            }
        }

        if (HANDLER_CONSOLE && !alreadyHasConsole) {

            ConsoleHandler ch = new ConsoleHandler();
            ch.setLevel(logOutPutLevel);
            logger.addHandler(ch);
        }

        if (HANDLER_FILE && !alreadyHasFile) {

            String file = getLogFileName(logger.getName());

            File f = new File(LOG_FILE_PATH);
            if (!f.isDirectory()) {
                f.mkdirs();
                f.mkdir();
            }
            try {
                MyFileHandler fh = new MyFileHandler(file, FILE_SIZE, FILE_MAX, true);
                fh.setLevel(logOutPutLevel);
                logger.addHandler(fh);
            } catch (IOException ex) {
                Logger.getLogger(Log.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SecurityException ex) {
                Logger.getLogger(Log.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
    }

    /**
     * 格式化时间到字符串
     * 
     * @param pattern 格式
     * @param date 时间
     * @return 格式化的字符串
     */
    private String getDateFormat(String pattern, Date date) {
        format.applyPattern(pattern);
        return format.format(date);
    }

    /**
     * 设置输出等级
     * 
     * @param level 自定义等级,可使用 debug,info,warn,error 忽略大小写
     */
    public final void setLogLevel(String level) {
        logOutPutLevel = getLogLevelFromString(level);
    }

    private void checkFileDate(String level) {
        File f = new File(getLogFileName(level));
        if (!f.exists()) {
            for (Handler handler : Logger.getLogger(level).getHandlers()) {
                handler.close();
            }
            logList.remove(level);
        }
    }

    private static String LOG_FILE_PATH;
    private Level logOutPutLevel;
    private int FILE_SIZE;
    private int FILE_MAX;
    private boolean HANDLER_FILE = false;
    private boolean HANDLER_CONSOLE = false;
    private static ArrayList<String> logList = new ArrayList<String>();
    private String LOG_FILE_LASTNAME;
    private static String LEVEL_DEBUG = "DEBUG";
    private static String LEVEL_INFO = "INFO";
    private static String LEVEL_WARN = "WARN";
    private static String LEVEL_ERROR = "ERROR";
    private static Log INSTANCE = new Log();
    SimpleDateFormat format = new SimpleDateFormat();
}

/**
 * 自定义文件输出管理类,参考JDK FileHandler实现
 * 
 * @author DingFengHua
 */
class MyFileHandler extends StreamHandler {

    private MeteredStream meter;
    private boolean append;
    private int limit; // zero => no limit.
    private int count;
    private String pattern;
    private String lockFileName;
    private FileOutputStream lockStream;
    private File files[];
    private static final int MAX_LOCKS = 100;
    private static java.util.HashMap<String, String> locks = new java.util.HashMap<String, String>();

    private class MeteredStream extends OutputStream {

        OutputStream out;
        int written;

        MeteredStream(OutputStream out, int written) {
            this.out = out;
            this.written = written;
        }

        public void write(int b) throws IOException {
            out.write(b);
            written++;
        }

        @Override
        public void write(byte buff[]) throws IOException {
            out.write(buff);
            written += buff.length;
        }

        @Override
        public void write(byte buff[], int off, int len) throws IOException {
            out.write(buff, off, len);
            written += len;
        }

        @Override
        public void flush() throws IOException {
            out.flush();
        }

        @Override
        public void close() throws IOException {
            out.close();
        }
    }

    private void open(File fname, boolean append) throws IOException {
        int len = 0;
        if (append) {
            len = (int) fname.length();
        }
        FileOutputStream fout = new FileOutputStream(fname.toString(), append);
        BufferedOutputStream bout = new BufferedOutputStream(fout);
        meter = new MeteredStream(bout, len);
        setOutputStream(meter);
    }

    public MyFileHandler() throws IOException, SecurityException {
        openFiles();
    }

    public MyFileHandler(String pattern) throws IOException, SecurityException {
        if (pattern.length() < 1) {
            throw new IllegalArgumentException();
        }
        this.pattern = pattern;
        this.limit = 0;
        this.count = 1;
        openFiles();
    }

    public MyFileHandler(String pattern, boolean append) throws IOException, SecurityException {
        if (pattern.length() < 1) {
            throw new IllegalArgumentException();
        }
        this.pattern = pattern;
        this.limit = 0;
        this.count = 1;
        this.append = append;
        openFiles();
    }

    public MyFileHandler(String pattern, int limit, int count) throws IOException, SecurityException {
        if (limit < 0 || count < 1 || pattern.length() < 1) {
            throw new IllegalArgumentException();
        }
        this.pattern = pattern;
        this.limit = limit;
        this.count = count;
        openFiles();
    }

    public MyFileHandler(String pattern, int limit, int count, boolean append) throws IOException, SecurityException {
        if (limit < 0 || count < 1 || pattern.length() < 1) {
            throw new IllegalArgumentException();
        }
        this.pattern = pattern;
        this.limit = limit;
        this.count = count;
        this.append = append;
        openFiles();
    }

    private void openFiles() throws IOException {
        LogManager manager = LogManager.getLogManager();
        manager.checkAccess();
        if (count < 1) {
            throw new IllegalArgumentException("file count = " + count);
        }
        if (limit < 0) {
            limit = 0;
        }

        InitializationErrorManager em = new InitializationErrorManager();
        setErrorManager(em);

        int unique = -1;
        for (;;) {
            unique++;
            if (unique > MAX_LOCKS) {
                throw new IOException("Couldn't get lock for " + pattern);
            }
            lockFileName = generate(pattern, 0, unique).toString() + ".lck";
            synchronized (locks) {
                if (locks.get(lockFileName) != null) {
                    continue;
                }
                FileChannel fc;
                try {
                    lockStream = new FileOutputStream(lockFileName);
                    fc = lockStream.getChannel();
                } catch (IOException ix) {
                    continue;
                }
                try {
                    FileLock fl = fc.tryLock();
                    if (fl == null) {
                        continue;
                    }
                } catch (IOException ix) {
                }
                locks.put(lockFileName, lockFileName);
                break;
            }
        }

        files = new File[count];
        for (int i = 0; i < count; i++) {
            files[i] = generate(pattern, i, unique);
        }
        if (append) {
            open(files[0], true);
        } else {
            rotate();
        }
        Exception ex = em.lastException;
        if (ex != null) {
            if (ex instanceof IOException) {
                throw (IOException) ex;
            } else if (ex instanceof SecurityException) {
                throw (SecurityException) ex;
            } else {
                throw new IOException("Exception: " + ex);
            }
        }
        setErrorManager(new ErrorManager());
    }

    private File generate(String pattern, int generation, int unique) throws IOException {
        File file = null;
        String word = "";
        int ix = 0;
        boolean sawg = false;
        boolean sawu = false;
        while (ix < pattern.length()) {
            char ch = pattern.charAt(ix);
            ix++;
            char ch2 = 0;
            if (ix < pattern.length()) {
                ch2 = Character.toLowerCase(pattern.charAt(ix));
            }
            if (ch == '/') {
                if (file == null) {
                    file = new File(word);
                } else {
                    file = new File(file, word);
                }
                word = "";
                continue;
            } else if (ch == '%') {
                if (ch2 == 't') {
                    String tmpDir = System.getProperty("java.io.tmpdir");
                    if (tmpDir == null) {
                        tmpDir = System.getProperty("user.home");
                    }
                    file = new File(tmpDir);
                    ix++;
                    word = "";
                    continue;
                } else if (ch2 == 'h') {
                    file = new File(System.getProperty("user.home"));
                    if (isSetUID()) {
                        throw new IOException("can't use %h in set UID program");
                    }
                    ix++;
                    word = "";
                    continue;
                } else if (ch2 == 'g') {
                    word = word + generation;
                    sawg = true;
                    ix++;
                    continue;
                } else if (ch2 == 'u') {
                    word = word + unique;
                    sawu = true;
                    ix++;
                    continue;
                } else if (ch2 == '%') {
                    word = word + "%";
                    ix++;
                    continue;
                }
            }
            word = word + ch;
        }
        if (count > 1 && generation > 0 && !sawg) {
            word = word + "." + generation;
        }
        if (unique > 0 && !sawu) {
            word = word + "." + unique;
        }
        if (word.length() > 0) {
            if (file == null) {
                file = new File(word);
            } else {
                file = new File(file, word);
            }
        }
        return file;
    }

    private synchronized void rotate() {
        Level oldLevel = getLevel();
        setLevel(Level.OFF);

        super.close();
        for (int i = count - 2; i >= 0; i--) {
            File f1 = files[i];
            File f2 = files[i + 1];
            if (f1.exists()) {
                if (f2.exists()) {
                    f2.delete();
                }
                f1.renameTo(f2);
            }
        }
        try {
            open(files[0], false);
        } catch (IOException ix) {
            reportError(null, ix, ErrorManager.OPEN_FAILURE);

        }
        setLevel(oldLevel);
    }

    @Override
    public synchronized void publish(LogRecord record) {
        if (!isLoggable(record)) {
            return;
        }
        super.publish(record);
        flush();
        if (limit > 0 && meter.written >= limit) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {

                public Object run() {
                    rotate();
                    return null;
                }
            });
        }
    }

    @Override
    public synchronized void close() throws SecurityException {
        super.close();
        if (lockFileName == null) {
            return;
        }
        try {
            lockStream.close();
        } catch (Exception ex) {
        }
        synchronized (locks) {
            locks.remove(lockFileName);
        }
        new File(lockFileName).delete();
        lockFileName = null;
        lockStream = null;
    }

    private static class InitializationErrorManager extends ErrorManager {

        Exception lastException;

        @Override
        public void error(String msg, Exception ex, int code) {
            lastException = ex;
        }
    }

    private static native boolean isSetUID();

}
 
0
0
分享到:
评论

相关推荐

    log4j2漏洞检测工具

    **Log4j2漏洞检测工具详解** 在当前的IT环境中,安全问题日益凸显,特别是针对开源组件的安全漏洞。Log4j2,一个广泛使用的Java日志框架,最近曝出的重大安全漏洞(CVE-2021-44228,被称为Log4Shell)引起了全球的...

    若依框架使用的log4j2.16.0,修复log4j漏洞log4j2下载最新log4j2.16.0下载

    通常,更新Log4j2的步骤包括下载最新的JAR文件,替换旧版本的JAR,或者通过Maven或Gradle等构建工具更新依赖。 标签“若依 log4j2.16.0”明确了这个问题针对的是若依框架中的Log4j2组件,提醒用户要特别关注这个...

    Apache Log4j2 远程代码执行漏洞检测工具

    1. 扫描系统及应用的类路径,寻找Log4j2的依赖。 2. 检查Linux服务器上的各种服务和应用程序,确定它们是否使用了易受攻击的Log4j2版本。 3. 在容器环境下,如Docker,也能有效地进行安全检查。 4. 可能支持自动化...

    log4j漏洞扫描工具

    “log4j漏洞扫描工具”是指用于检测和识别Apache Log4j框架中存在安全漏洞的专用软件。Log4j是Java编程语言中的一个流行日志记录库,2021年曝光的重大安全漏洞(被称为CVE-2021-44228或Log4Shell)使得恶意攻击者...

    日志组件-仿log4j的配置

    这篇博客“日志组件-仿log4j的配置”探讨了如何设计和实现一个模仿Log4j的日志解决方案。 首先,我们需要理解Log4j的基本工作原理。Log4j包含三个主要部分:Logger(日志器)、Appender(输出端)和Layout(格式化...

    log4j-API-最新稳定版本log4j-1.2.17

    总的来说,Log4j API为Java开发者提供了一个强大而灵活的日志解决方案,通过其丰富的功能和可定制性,能够适应各种项目的需求。对于使用Log4j的开发者来说,理解和掌握API的各个方面至关重要,以实现有效的日志管理...

    log4j-api-2.12.4.ja和log4j-core-2.12.4.jar

    总的来说,Log4j 2是Java开发中不可或缺的工具,它提供强大的日志记录能力并注重性能和可扩展性。在选择和使用特定版本时,应密切关注安全更新,确保及时修补任何潜在的安全风险,以保护应用程序和用户数据的安全。...

    log4j-1.2.15.jar

    1. **引入依赖**:在项目中添加Log4j 1.2.15.jar依赖,可以手动下载放入类路径,或者通过Maven或Gradle等构建工具进行管理。 2. **配置文件**:创建log4j.properties或log4j.xml配置文件,设置日志级别、Appender、...

    log4j.jar包,和log4j.properties配置文件下载

    在实际应用中,将`log4j.jar`添加到项目的类路径中,并根据项目需求定制`log4j.properties`,即可实现有效的日志管理。这不仅有助于问题排查,也有利于系统维护和性能优化,因为过多的日志可能会占用大量磁盘空间,...

    Log4J完整说明和配置

    ### Log4J完整说明与配置解析 #### 一、Log4J简介 Log4J是Apache的一个开源项目,用于提供灵活的日志记录功能。通过它,开发者能够控制日志信息的输出级别、输出目的地(控制台、文件等)、格式化方式等。本文将...

    log4j实用配置扩展

    #### 四、log4j的核心组件 log4j的核心组件主要包括**Loggers(记录器)**、**Appenders(输出源)**和**Layouts(布局)**。 1. **Loggers (记录器)**:负责生成日志信息,并决定是否发送日志信息到Appenders。记录器...

    Log4j将System.out搞到log4j中输出四

    我们可以创建一个定制的PrintStream类,重写`print()`和`println()`方法,将调用转发给Log4j的Logger。下面是一个简单的实现: ```java public class Log4jPrintStream extends PrintStream { private Logger ...

    log4j简单使用

    - `log4j-1.2.14.jar`: 这是Log4j 1.2.14版本的jar包,包含了Log4j的全部类和方法,是使用Log4j进行日志记录的核心组件。 - `commons-logging-1.0.4.jar`: 这是Apache Commons Logging库,它是Java日志API的一个抽象...

    apache-log4j-1.2.16.rar_apache log4j 1.2.16_log4j source code_lo

    通过分析和学习Log4j的源代码,开发者可以更好地理解和利用这个强大的工具,解决在实际项目中遇到的日志问题,定制自己的日志解决方案,或者为开源社区贡献新的特性或修复已知问题。总之,熟悉并掌握Log4j的内部工作...

    新版本与旧版本log4j.jar包下载,附使用说明----.zip

    3. **IDEA与log4j**: IntelliJ IDEA(简称IDEA)是一款流行的Java集成开发环境,它支持将log4j集成到项目中,通过配置pom.xml或build.gradle文件添加依赖,或者手动将log4j.jar添加到项目的类路径下,以便在IDEA中...

    log4j 工具类 多个日志文件

    Log4j是Apache组织提供的一款广泛使用的Java日志框架,因其高效、灵活和强大的功能而备受青睐。 **Log4j简介** Log4j是一个开源的日志记录库,主要设计用于Java应用程序。它允许程序员以可配置的方式控制日志信息...

    log4j使用jar文件

    总结来说,Log4j是一个强大的日志工具,它通过配置文件和简单的API为Java应用程序提供了定制化的日志记录功能。理解和掌握Log4j的使用,对于任何Java开发者来说都是十分有益的,因为它能够帮助优化调试过程,提升...

    log4j.1.2.17

    Log4j,作为Java世界中最广泛使用的日志框架之一,因其强大的功能和灵活的配置,成为了开发者的首选工具。本文将重点围绕Log4j 1.2.17版本展开,详细介绍其核心概念、使用方法以及配置细节。 1. **Log4j简介** Log...

    log4j-2.17.1的jar包,导入即可使用

    3. **导入使用**:在Java项目中使用Log4j非常简单,只需要将`log4j-2.17.1.jar`文件添加到项目的类路径(Classpath)中。对于Maven或Gradle项目,可以在依赖管理中添加相应的依赖条目。 4. **配置文件**:Log4j 的...

    log4j配置和加载方法

    Log4j是一款由Apache出品的日志记录工具,它提供了灵活的日志级别控制和多样化的日志输出方式,广泛应用于Java应用的开发中。本文将深入解析log4j的配置与加载机制,帮助开发者更好地理解和应用log4j。 #### Log4j...

Global site tag (gtag.js) - Google Analytics