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

╰半橙微兮° 2022-10-22 12:54 79阅读 0赞

Java日志体系

  • 日志实现 JUL、logback、log4j、log4j2
  • JUL日志级别 java.util.logging.Level
  • 示例讲解功能
    • JULTest 测试类 test方法 不同日志输出方法
    • testLogConsoleConfig方法 控制台输出测试
    • testLogFileConfig方法 输出文件测试
    • 日志对象父子关系
    • testLogProperties配置文件方式
  • 日志原理解析

日志实现 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方法 不同日志输出方法

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

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

输出结果:

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

testLogConsoleConfig方法 控制台输出测试

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

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

  1. @Test
  2. public void testLogConsoleConfig(){
  3. //获取日志记录器对象
  4. Logger logger = Logger.getLogger("cn.ling.logs.JULTest");
  5. logger.severe("severe");
  6. logger.warning("warning");
  7. logger.info("info");
  8. logger.config("config");
  9. logger.fine("fine");
  10. logger.finer("finer");
  11. logger.finest("finest");
  12. }

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

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

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

  1. @Test
  2. public void testLogConsoleConfig(){
  3. //获取日志记录器对象
  4. Logger logger = Logger.getLogger("cn.ling.logs.JULTest");
  5. //关闭默认日志级别
  6. logger.setUseParentHandlers(false);
  7. //输出到控制台
  8. ConsoleHandler consoleHandler = new ConsoleHandler();
  9. //输出格式
  10. SimpleFormatter simpleFormatter = new SimpleFormatter();
  11. consoleHandler.setFormatter(simpleFormatter);
  12. //输出控制台的日志级别
  13. consoleHandler.setLevel(Level.ALL);
  14. logger.addHandler(consoleHandler);
  15. //日志输出级别
  16. logger.setLevel(Level.CONFIG);
  17. logger.severe("severe");
  18. logger.warning("warning");
  19. logger.info("info");
  20. logger.config("config");
  21. logger.fine("fine");
  22. logger.finer("finer");
  23. logger.finest("finest");
  24. }

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

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

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

  1. 三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
  2. 严重: severe
  3. 三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
  4. 严重: severe
  5. 三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
  6. 警告: warning
  7. 三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
  8. 警告: warning
  9. 三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
  10. 信息: info
  11. 三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
  12. 信息: info
  13. 三月 17, 2021 2:26:30 下午 cn.ling.logs.JULTest testLogConsoleConfig
  14. 配置: config

testLogFileConfig方法 输出文件测试

  1. @Test
  2. public void testLogFileConfig() throws IOException {
  3. //获取日志记录器对象
  4. Logger logger = Logger.getLogger("cn.ling.logs.JULTest");
  5. //关闭默认日志级别
  6. logger.setUseParentHandlers(false);
  7. //输出到控制台
  8. ConsoleHandler consoleHandler = new ConsoleHandler();
  9. //输出格式
  10. SimpleFormatter simpleFormatter = new SimpleFormatter();
  11. consoleHandler.setFormatter(simpleFormatter);
  12. //输出控制台的日志级别
  13. consoleHandler.setLevel(Level.ALL);
  14. FileHandler fileHandler = new FileHandler("D:/logs/jul.log");
  15. fileHandler.setFormatter(simpleFormatter);
  16. logger.addHandler(fileHandler);
  17. //日志输出级别
  18. logger.setLevel(Level.CONFIG);
  19. logger.severe("severe");
  20. logger.warning("warning");
  21. logger.info("info");
  22. logger.config("config");
  23. logger.fine("fine");
  24. logger.finer("finer");
  25. logger.finest("finest");
  26. }

输出结果:

  1. java.nio.file.NoSuchFileException: D:\logs\jul.log.lck
  2. at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)
  3. at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
  4. at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
  5. at sun.nio.fs.WindowsFileSystemProvider.newFileChannel(WindowsFileSystemProvider.java:115)
  6. at java.nio.channels.FileChannel.open(FileChannel.java:287)
  7. at java.nio.channels.FileChannel.open(FileChannel.java:335)
  8. at java.util.logging.FileHandler.openFiles(FileHandler.java:459)
  9. at java.util.logging.FileHandler.<init>(FileHandler.java:292)
  10. at cn.ling.logs.JULTest.testLogFileConfig(JULTest.java:73)
  11. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  12. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  13. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  14. at java.lang.reflect.Method.invoke(Method.java:498)
  15. at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
  16. at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  17. at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
  18. at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
  19. at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
  20. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
  21. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
  22. at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
  23. at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
  24. at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
  25. at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
  26. at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
  27. at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
  28. at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
  29. at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
  30. at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
  31. at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
  32. at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)

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

日志对象父子关系

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

  1. @Test
  2. public void testLogParent(){
  3. Logger loggerF = Logger.getLogger("cn.ling.logs");
  4. Logger loggerS = Logger.getLogger("cn.ling.logs.JULTest");
  5. System.out.println("loggerF==loggerS 结果:"+(loggerF==loggerS.getParent()));//true
  6. //关闭默认配置 如果修改为true子日志对象和父对象同事打印日志
  7. loggerF.setUseParentHandlers(false);
  8. ConsoleHandler consoleHandler = new ConsoleHandler();
  9. SimpleFormatter simpleFormatter = new SimpleFormatter();
  10. consoleHandler.setFormatter(simpleFormatter);
  11. loggerF.addHandler(consoleHandler);
  12. loggerF.setLevel(Level.ALL);
  13. consoleHandler.setLevel(Level.ALL);
  14. //日志级别
  15. loggerS.severe("severe");
  16. loggerS.warning("warning");
  17. loggerS.info("info");
  18. loggerS.config("config");
  19. loggerS.fine("fine");
  20. loggerS.finer("finer");
  21. loggerS.finest("finest");
  22. }

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

  1. loggerF==loggerS 结果:true
  2. 三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
  3. 严重: severe
  4. 三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
  5. 警告: warning
  6. 三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
  7. 信息: info
  8. 三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
  9. 配置: config
  10. 三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
  11. 详细: fine
  12. 三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
  13. 较详细: finer
  14. 三月 17, 2021 2:34:52 下午 cn.ling.logs.JULTest testLogParent
  15. 非常详细: finest

testLogProperties配置文件方式

创建配置文件logging.properties

  1. ##RootLogger使用的处理器(获取时设置):顶级父元素
  2. handlers=java.util.logging.ConsoleHandler,java.util.logging.FileHandler
  3. #RootLogger日志等级
  4. .level=INFO
  5. ##自定义Logger
  6. #cn.ling.handlers=java.util.logging.FileHandler
  7. #自定义Logger日志等级
  8. #cn.ling.level=INFO
  9. #忽略父日志设置
  10. #cn.ling.useParentHandlers=false
  11. ##控制台处理器
  12. #输出日志级别
  13. java.util.logging.ConsoleHandler.level=INFO
  14. #指定handler对象的字符集
  15. java.util.logging.ConsoleHandler.encoding=UTF-8
  16. #输出日志格式
  17. java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
  18. ##文件处理器
  19. #输出日志级别
  20. java.util.logging.FileHandler.level=INFO
  21. #指定 handler 对象日志消息格式对象 SimpleFormatter 或者 XMLFormatter
  22. java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
  23. #输出日志文件路径
  24. java.util.logging.FileHandler.pattern=D:/logs/jul.log
  25. #输出日志文件限制大小(50000字节)
  26. java.util.logging.FileHandler.limit=50000
  27. #输出日志文件限制个数
  28. java.util.logging.FileHandler.count=10
  29. #输出日志文件 是否是追加(不会覆盖前边的日志)
  30. java.util.logging.FileHandler.append=true
  31. # 指定日志消息格式
  32. java.util.logging.SimpleFormatter.format = %4$s: %5$s [%1$tc]%n

测试代码:

  1. @Test
  2. public void testLogProperties() throws IOException {
  3. InputStream resourceAsStream = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");
  4. Logger logger = Logger.getLogger("cn.ling.logs.JULTest");
  5. LogManager manager = LogManager.getLogManager();
  6. manager.readConfiguration(resourceAsStream);
  7. logger.severe("severe");
  8. logger.warning("warning");
  9. logger.info("info");
  10. logger.config("config");
  11. logger.fine("fine");
  12. logger.finer("finer");
  13. logger.finest("finest");
  14. }

console输出结果:

  1. 严重: severe [星期三 三月 17 14:39:00 CST 2021]
  2. 警告: warning [星期三 三月 17 14:39:00 CST 2021]
  3. 信息: 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的

发表评论

表情:
评论列表 (有 0 条评论,79人围观)

还没有评论,来说两句吧...

相关阅读

    相关 日志框架(一)JUL

    一、日志的概念 1. 日志文件 日志文件是用于记录系统操作事件的文件集合,可分为事件日志和消息日志。具有处理历史数据、诊断问题的追踪以及理解系统的活动等重要作用。

    相关 Java 日志体系详解

    概要 本文的目的是搞清楚Java中各种日志Log之间是怎么的关系,如何作用、依赖,好让我们平时在工作中如果遇到“日志打不出”或者“日志jar包冲突”等之类的问题知道该如何

    相关 Java 日志体系详解

    本文的目的是搞清楚Java中各种日志Log之间是怎么的关系,如何作用、依赖,好让我们平时在工作中如果遇到“日志打不出”或者“日志jar包冲突”等之类的问题知道该如何入手解决,以

    相关 Java日志体系

    > 日志框架可以说是软件系统的标配,平时使用日志的时候多数只是了解日志配置怎么配,对于这些日志框架的不同以及他们之间的关系很少了解。 Java中的日志体系可以用杂乱无章来形容