Java 日志框架简介

一.Java日志框架历史总体概述

Java框架现在主要是分为两个大的日志门面: JCL、slf4j

日志框架的实现主要是一下这几种 JUL(java原生自带)、logback()、log4j、log4j2

历史及总体简介等我稍后了解完毕之后在进行编写,稍后再继续编写吧,先说明怎么进行使用哈>>>   ^_^

二. JUL(Java Util Logging)简介

JUL是sun公司推出的jdk原生的日志框架,使用JUL无需进行导入包

JUL的日志级别

JUL的日志主要分为一下几个级别:

          SEVERE(最高值)
          WARNING
          INFO (默认级别)
          CONFIG
          FINE
          FINER
          FINEST(最低值)
          
* 还有两个特殊的级别:

          OFF,可用来关闭日志记录。
          ALL,启用所有消息的日志记录。

简单的输出INFO日志的示例:

首先获取日志记录器对象,其实这个里面随便填啥都能使用,但是不能填写空字符串. 默认的日志输出级别即为INFO级别,低于INFO级别的都不会进行输出

    @Test
    public void test1() {
        // 获取日志记录器对象
        Logger logger = Logger.getLogger("com.huqi.JULTest");
        // 日志记录输出
        logger.info("hello jul");

        // 通用方法进行日志记录
        logger.log(Level.INFO, "info msg");

        System.out.printf("-------------------------------------------------------------");
        
        String name  = "胡琦";
        Integer age = 24;
        // 自带的占位符转换
        logger.log(Level.INFO, "name  = {0}, age = {1}", new Object[]{name, age});
    }

在这里插入图片描述

输出各个级别的日志信息

	@Test
    public void test2() throws IOException {
        // 获取日志记录器对象
        Logger logger = Logger.getLogger("com.huqi.JULTest");

        // 关闭jul默认的日志级别
        logger.setUseParentHandlers(false);

        // 一个日志格式处理器
        SimpleFormatter simpleFormatter = new SimpleFormatter();

        // 控制台处理器, 输出信息控制台
        ConsoleHandler consoleHandler = new ConsoleHandler();
        consoleHandler.setFormatter(simpleFormatter);

        // 文件处理器, 输出到文件去
        FileHandler fileHandler = new FileHandler("D:/test.log");
        fileHandler.setFormatter(simpleFormatter);

        // 将处理器添加到日志记录器对象中
        logger.addHandler(consoleHandler);
        logger.addHandler(fileHandler);

        // 设置自己需要的细粒度,全部开启
        logger.setLevel(Level.ALL);
        consoleHandler.setLevel(Level.ALL);
        fileHandler.setLevel(Level.ALL);

        // 现在可以输出所有的日志级别了
        logger.fine("fine");
        logger.finer("fine");
        logger.finest("fine");
        logger.info("fine");
        logger.warning("fine");
        logger.severe("fine");
        logger.config("fine");
    }

控制台打印的信息
在这里插入图片描述
输出在D盘的日志文件
在这里插入图片描述

Logger的父子关系

    /**
     *  logger 的父子关系
     */
    @Test
    public void test3() {
        //分别获取父子包的两个日志对象
        Logger logger1 = Logger.getLogger("com.huqi");
        Logger logger2 = Logger.getLogger("com");

        // true
        System.out.println(logger1.getParent() == logger2);

        // 获取日志记录器的顶级父元素  LogManager$RootLogger  name = ""
        // logger2 Parent: java.util.logging.LogManager$RootLogger@deb6432 ,name :
        System.out.println("logger2 Parent: " + logger2.getParent() +
                " ,name : " + logger2.getParent().getName());

        // 关闭默认日志级别配置
        logger2.setUseParentHandlers(false);

        // 设置处理器
        ConsoleHandler consoleHandler = new ConsoleHandler();
        SimpleFormatter simpleFormatter = new SimpleFormatter();
        consoleHandler.setFormatter(simpleFormatter);

        logger2.addHandler(consoleHandler);

        // 设置了父的日志级别全开
        logger2.setLevel(Level.ALL);
        consoleHandler.setLevel(Level.ALL);


        // logger1继承了logger2的日志设置,可以进行输出所有的日志级别
        // 现在可以输出所有的日志级别了
        logger1.fine("fine");
        logger1.finer("fine");
        logger1.finest("fine");
        logger1.info("fine");
        logger1.warning("fine");
        logger1.severe("fine");
        logger1.config("fine");
    }

在这里插入图片描述

使用配置文件来控制日志的输出级别

    /**
     * 加载自定义配置文件
     */
    @Test
    public void test4() throws IOException {
        // 读取配置文件, 通过类加载器
        InputStream resource = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");
        // 创建LogManager
        LogManager logManager = LogManager.getLogManager();
        // 通过LogManager配置文件
        logManager.readConfiguration(resource);

        // 创建日志记录器
        Logger logger = Logger.getLogger("com.huqi");
        logger.fine("fine");
        logger.finer("fine");
        logger.finest("fine");
        logger.info("fine");
        logger.warning("fine");
        logger.severe("fine");
        logger.config("fine");
    }

logging.properties

# 默认的处理器: 控制台输出
handlers =java.util.logging.ConsoleHandler
# 默认的日志级别是info
.level = ALL

# 格式处理器
# 默认的处理器: 控制台输出  文件输出
handlers =java.util.logging.ConsoleHandler,java.util.logging.FileHandler
# 默认的日志级别是info
.level = ALL

java.util.logging.ConsoleHandler.formatter = org.springframework.boot.logging.java.SimpleFormatter
java.util.logging.ConsoleHandler.level = ALL

java.util.logging.FileHandler.pattern = D://java%u.Log
java.util.logging.FileHandler.limit = 50000
java.utiL.logging.FiLeHandler.count = 1
java.utiL.logging.FileHandler.formatter = java.util.logging.XMLFormatter


org.hibernate.validator.internal.util.Version.level = WARNING
org.apache.coyote.http11.Http11NioProtocol.level = WARNING
org.apache.tomcat.util.net.NioSelectorPool.level = WARNING
org.apache.catalina.startup.DigesterFactory.level = SEVERE
org.apache.catalina.util.LifecycleBase.level = SEVERE
org.eclipse.jetty.util.component.AbstractLifeCycle.level = SEVERE

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

具体如何使用日志框架以及如何包装日志的工具类,可看参考此github链接的日志工具类,使用的是slfj+logback进行日志的输出.
https://gitee.com/huqidake/spring-boot-demo

可参考如下的代码进行配置,使用那个的是xml文件,同样也可以使用一个yml文件操作.

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="LOG_HOME" value="/home" />
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<!--            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%logger{50}] - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
package com.huqi.log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.MessageFormat;

/**
 * 日志工具类
 * @author 胡琦
 * @date 2021-07-24 星期六 16:03
 */
public class LoggerUtil {
    private final static Logger LOGGER = LoggerFactory.getLogger(LoggerUtil.class);

    public static void info(Logger logger, String template, String... args) {
        if (logger.isInfoEnabled()) {
            logger.info(joint(template, args));
        }
    }

    public static void warn(Logger logger, String template, String... args) {
        logger.warn(joint(template, args));
    }

    public static void warn(Throwable throwable, Logger logger, String template, String... args) {
        logger.warn(joint(template, args), throwable);
    }

    public static void error(Logger logger, String template, String... args) {
        logger.error(joint(template, args));
    }

    public static void error(Throwable throwable, Logger logger, String template, String... args) {
        logger.error(joint(template, args), throwable);
    }

    /**
     * 解析占位符,返回拼接好的字符串
     *
     *
     * 我自己的实现方式
     *
     *     // {
     *     private static final char PREFIX = 123;
     *     // }
     *     private static final char SUFFIX = 125;
     *
     *     private static Set numSet = new HashSet(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
     *
     * private static String joint(String msg, String... msgs) {
     *         if (StringUtils.isBlank(msg) || msg == null || msgs.length == 0) {
     *             return msg;
     *         }
     *         final char[] chars = msg.toCharArray();
     *         StringBuilder stringBuilder = new StringBuilder();
     *         try {
     *             for (int i = 0; i < chars.length;) {
     *                 char c = chars[i];
     *                 if (c == PREFIX && chars[i+2] == SUFFIX) {
     *                     Integer index = Integer.valueOf(Character.toString(chars[i + 1]));
     *                     boolean contains = numSet.contains(index);
     *                     if (contains) {
     *                         stringBuilder.append(msgs[index]);
     *                     }
     *                     i = i+2;
     *                     continue;
     *                 }
     *                 if (c == SUFFIX) {
     *                     i++;
     *                     continue;
     *                 }
     *                 stringBuilder.append(c);
     *                 i++;
     *             }
     *         }catch (Exception e) {
     *             LOGGER.error("LoggerUtils joint error");
     *             return msg;
     *         }
     *         return stringBuilder.toString();
     *     }
     *
     *
     * @param msg  模板参数 示例
     *                          test1 = {0}, test2 = {1}
     *             填充的参数从0开始,数字和花括号之间不能有空格
     * @param args 需要填充的参数,
     * @return
     */
    private static String joint(String msg, String... args) {
        try {
            return MessageFormat.format(msg, args);
        } catch (Exception e) {
            LOGGER.error("日志打印异常", e);
        }
        return null;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值