Java日志体系(三) jul 配置文件详解,日志示例
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方法 不同日志输出方法
获取日志记录器,使用不同的方法打印日志。
/** * 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]
**日志文件如下:**重复使因为我执行了两次的原因。
日志原理解析
- 初始化LogManager
LogManager加载logging.properties配置
添加Logger到LogManager - 从单例LogManager获取Logger
- 设置级别Level,并指定日志记录LogRecord
- Filter提供了日志级别之外更细粒度的控制
- Handler是用来处理日志输出位置
- Formatter是用来格式化LogRecord的
还没有评论,来说两句吧...