Java日志体系(三) jul 配置文件详解,日志示例

日志实现 JUL、logback、log4j、log4j2

在这里插入图片描述

  • Loggers:被称为记录器,应用程序通过获取Logger对象,调用其API来来发布日志信息。Logger通常时应用程序访问日志系统的入口程序。
  • Appenders:也被称为Handlers,每个Logger都会关联一组Handlers,Logger会将日志交给关联Handlers处理,由Handlers负责将日志做记录。Handlers在此是一个抽象,其具体的实现决定了日志记录的位置可以是控制台、文件、网络上的其他日志服务或操作系统日志等。
  • Layouts:也被称为Formatters,它负责对日志事件中的数据进行转换和格式化。Layouts决定了数据在一条日志记录中的最终形式。
  • Level:每条日志消息都有一个关联的日志级别。该级别粗略指导了日志消息的重要性和紧迫,我可以将Level和Loggers,Appenders做关联以便于我们过滤消息。
  • Filters:过滤器,根据需要定制哪些信息会被记录,哪些信息会被放过。

JUL日志级别 java.util.logging.Level

各级别按降序排列如下:

  • SEVERE(最高值):SEVERE 是指示严重失败的消息级别
  • WARNING :WARNING 是指示潜在问题的消息级别
  • INFO :INFO 是报告消息的消息级别
  • CONFIG :CONFIG 是用于静态配置消息的消息级别
  • FINE :FINE 是提供跟踪信息的消息级别
  • FINER :FINEST 指示一条最详细的跟踪消息
  • FINEST(最低值):FINEST 指示一条最详细的跟踪消息

特殊级别

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

示例讲解功能

创建maven工程,因为jul是java的jdk提供的日志,所以不需要添加jar包。直接使用。

JULTest 测试类 test方法 不同日志输出方法

获取日志记录器,使用不同的方法打印日志。

/**
 * java 原生日志jul测试
 */
public class JULTest {
    @Test
    public void  test(){
        //获取日志记录器对象
        Logger logger = Logger.getLogger("cn.ling.logs.JULTest");
        //日志记录输出
        logger.info("Hello JUL");
        //通用方法进行日志记录
        logger.log(Level.INFO, "JUL log");
        //占位符方式输出变量值
        logger.log(Level.INFO,"用户信息:{0},{1}",new Object[]{"小美",18});
    }
}

输出结果:

三月 17, 2021 2:13:02 下午 cn.ling.logs.JULTest test
信息: Hello JUL
三月 17, 2021 2:13:02 下午 cn.ling.logs.JULTest test
信息: JUL log
三月 17, 2021 2:13:02 下午 cn.ling.logs.JULTest test
信息: 用户信息:小美,18

testLogConsoleConfig方法 控制台输出测试

下面只有测试方法代码,放到上面测试类里面即可:

使用默认日志级别Info执行代码:

@Test
    public void testLogConsoleConfig(){
        //获取日志记录器对象
        Logger logger = Logger.getLogger("cn.ling.logs.JULTest");
        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
    }

输出结果:日志级别在info之下的日志不会输出:

三月 17, 2021 2:17:52 下午 cn.ling.logs.JULTest testLogConsoleConfig
严重: severe
三月 17, 2021 2:17:52 下午 cn.ling.logs.JULTest testLogConsoleConfig
警告: warning
三月 17, 2021 2:17:52 下午 cn.ling.logs.JULTest testLogConsoleConfig
信息: info

关闭默认日志级别:logger.setUseParentHandlers(false)

@Test
    public void testLogConsoleConfig(){
        //获取日志记录器对象
        Logger logger = Logger.getLogger("cn.ling.logs.JULTest");
        //关闭默认日志级别
        logger.setUseParentHandlers(false);

        //输出到控制台
        ConsoleHandler consoleHandler = new ConsoleHandler();

        //输出格式
        SimpleFormatter simpleFormatter = new SimpleFormatter();
        consoleHandler.setFormatter(simpleFormatter);
        //输出控制台的日志级别
        consoleHandler.setLevel(Level.ALL);

        logger.addHandler(consoleHandler);
        //日志输出级别
        logger.setLevel(Level.CONFIG);

        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
    }

输出结果:consoleHandler.setLevel(Level.ALL); 输出所有;logger.setLevel(Level.CONFIG);输出config级别。两者取范围最小的,即日志级别最大哪个作为输出标准

三月 17, 2021 2:23:15 下午 cn.ling.logs.JULTest testLogConsoleConfig
严重: severe
三月 17, 2021 2:23:15 下午 cn.ling.logs.JULTest testLogConsoleConfig
警告: warning
三月 17, 2021 2:23:15 下午 cn.ling.logs.JULTest testLogConsoleConfig
信息: info
三月 17, 2021 2:23:15 下午 cn.ling.logs.JULTest testLogConsoleConfig
配置: config

如果logger.setUseParentHandlers(false)不设置为false,将会重复输出info以上的日志。如下

三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
严重: severe
三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
严重: severe
三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
警告: warning
三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
警告: warning
三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
信息: info
三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
信息: info
三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
配置: config

testLogFileConfig方法 输出文件测试

@Test
    public void testLogFileConfig() throws IOException {
        //获取日志记录器对象
        Logger logger = Logger.getLogger("cn.ling.logs.JULTest");
        //关闭默认日志级别
        logger.setUseParentHandlers(false);

        //输出到控制台
        ConsoleHandler consoleHandler = new ConsoleHandler();

        //输出格式
        SimpleFormatter simpleFormatter = new SimpleFormatter();
        consoleHandler.setFormatter(simpleFormatter);
        //输出控制台的日志级别
        consoleHandler.setLevel(Level.ALL);

        FileHandler fileHandler = new FileHandler("D:/logs/jul.log");
        fileHandler.setFormatter(simpleFormatter);
        logger.addHandler(fileHandler);

        //日志输出级别
        logger.setLevel(Level.CONFIG);

        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
    }

输出结果:

java.nio.file.NoSuchFileException: D:\logs\jul.log.lck

	at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)
	at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
	at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
	at sun.nio.fs.WindowsFileSystemProvider.newFileChannel(WindowsFileSystemProvider.java:115)
	at java.nio.channels.FileChannel.open(FileChannel.java:287)
	at java.nio.channels.FileChannel.open(FileChannel.java:335)
	at java.util.logging.FileHandler.openFiles(FileHandler.java:459)
	at java.util.logging.FileHandler.<init>(FileHandler.java:292)
	at cn.ling.logs.JULTest.testLogFileConfig(JULTest.java:73)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)

输出目录不存在,需要添加目录
在这里插入图片描述

日志对象父子关系

上面代码中的描述都比较详细,后面代码,如果描述的不够详细,希望自己去尝试尝试,这里仅仅把代码贴出来。

@Test
    public void testLogParent(){
        Logger loggerF = Logger.getLogger("cn.ling.logs");
        Logger loggerS = Logger.getLogger("cn.ling.logs.JULTest");
        System.out.println("loggerF==loggerS 结果:"+(loggerF==loggerS.getParent()));//true

        //关闭默认配置 如果修改为true子日志对象和父对象同事打印日志
        loggerF.setUseParentHandlers(false);
        ConsoleHandler consoleHandler = new ConsoleHandler();
        SimpleFormatter simpleFormatter = new SimpleFormatter();
        consoleHandler.setFormatter(simpleFormatter);
        loggerF.addHandler(consoleHandler);
        loggerF.setLevel(Level.ALL);
        consoleHandler.setLevel(Level.ALL);
        //日志级别
        loggerS.severe("severe");
        loggerS.warning("warning");
        loggerS.info("info");
        loggerS.config("config");
        loggerS.fine("fine");
        loggerS.finer("finer");
        loggerS.finest("finest");
    }

**输出结果:**为什么比上面输出的日志多,因为日志级别不一样。

loggerF==loggerS 结果:true
三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
严重: severe
三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
警告: warning
三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
信息: info
三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
配置: config
三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
详细: fine
三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
较详细: finer
三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
非常详细: finest

testLogProperties配置文件方式

创建配置文件logging.properties

##RootLogger使用的处理器(获取时设置):顶级父元素
handlers=java.util.logging.ConsoleHandler,java.util.logging.FileHandler
#RootLogger日志等级
.level=INFO

##自定义Logger
#cn.ling.handlers=java.util.logging.FileHandler
#自定义Logger日志等级
#cn.ling.level=INFO
#忽略父日志设置
#cn.ling.useParentHandlers=false


##控制台处理器
#输出日志级别
java.util.logging.ConsoleHandler.level=INFO
#指定handler对象的字符集
java.util.logging.ConsoleHandler.encoding=UTF-8
#输出日志格式
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter

##文件处理器
#输出日志级别
java.util.logging.FileHandler.level=INFO
#指定 handler 对象日志消息格式对象 SimpleFormatter 或者 XMLFormatter
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
#输出日志文件路径
java.util.logging.FileHandler.pattern=D:/logs/jul.log
#输出日志文件限制大小(50000字节)
java.util.logging.FileHandler.limit=50000
#输出日志文件限制个数
java.util.logging.FileHandler.count=10
#输出日志文件 是否是追加(不会覆盖前边的日志)
java.util.logging.FileHandler.append=true

# 指定日志消息格式
java.util.logging.SimpleFormatter.format = %4$s: %5$s [%1$tc]%n

测试代码:

	@Test
    public void testLogProperties() throws IOException {
        InputStream resourceAsStream = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");
        Logger logger = Logger.getLogger("cn.ling.logs.JULTest");
        LogManager manager = LogManager.getLogManager();
        manager.readConfiguration(resourceAsStream);
        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
    }

console输出结果:

严重: severe [星期三 三月 17 14:39:00 CST 2021]
警告: warning [星期三 三月 17 14:39:00 CST 2021]
信息: info [星期三 三月 17 14:39:00 CST 2021]

**日志文件如下:**重复使因为我执行了两次的原因。
在这里插入图片描述

日志原理解析

在这里插入图片描述

  1. 初始化LogManager
    LogManager加载logging.properties配置
    添加Logger到LogManager
  2. 从单例LogManager获取Logger
  3. 设置级别Level,并指定日志记录LogRecord
  4. Filter提供了日志级别之外更细粒度的控制
  5. Handler是用来处理日志输出位置
  6. Formatter是用来格式化LogRecord的
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EngineerForSoul

你的鼓励是我孜孜不倦的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值