JUL 日志 - 最简单易用的Java日志框架

简介: JUL是最容易上手的Java日志框架,最适合初学者,本文一篇教会如何使用

在正式的生产环境下是不能使用 System.out 进行日志记录的
因为 System.out 不能提供时间、线程、执行过程 等信息,如果要手动打印输出则会非常麻烦
而日志就帮我们把这些事给干了
接下来我们学一个最简单的日志框架 JUL

JUL全称Java util Logging是java原生的日志框架,使用时不需要另外引用第三方类库

相对其他 日志框架,JUL 功能没那么强大,但是最方便使用,因此比较适合在小型应用中使用

JUL 架构

Logger持有若干个Handler,日志的输出操作是由Handler完成的

在Handler在输出日志前,会经过Filter的过滤,判断哪些日志级别过滤放行哪些拦截,Handler会将日
志内容输出到指定位置(日志文件、控制台等)

JUC 使用方法

        // 创建日志记录器对象
        Logger logger = Logger.getLogger("JULTest");
        // 通用方法进行日志记录
        logger.log(Level.INFO, "info msg");

在log中传入日志级别和日志信息,结果如下:

还可以直接调用 info 级别的方法 logger.info("info msg");

还可以使用占位符做拼接

        // 1.创建日志记录器对象
        Logger logger = Logger.getLogger("JULTest");

        String name = "张三";
        Integer age = 18;
        logger.log(Level.INFO, "用户信息:{0},{1}", new Object[]{
   name, age});

JUL的日志级别

JUL可以任务有9个日志级别

查看 Level 源码:

    public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);
    public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);
    public static final Level WARNING = new Level("WARNING", 900, defaultBundle);
    public static final Level INFO = new Level("INFO", 800, defaultBundle);
    public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);
    public static final Level FINE = new Level("FINE", 500, defaultBundle);
    public static final Level FINER = new Level("FINER", 400, defaultBundle);
    public static final Level FINEST = new Level("FINEST", 300, defaultBundle);
    public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);

每个级别的 Level 都会在构造时传入一个数,并且可以看到从OFF 到ALL 这个数越来越小

  • INFO - JUL默认的日志级别是 INFO ,INFO 对应的数值为800 ,那么数值大于等于800
    的日志级别是允许被执行的,而小于800 的是不允许执行的,INFO 用于记录常规的信息,比如数据库的连接信息、 IO的传递信息 、 网络的通信信息等
  • OFF - 因此当日志界别设置为OFF 时,对应的值是Integer.MAX_VALUE ,此时不会有数值更大的日志级别,也就不会有日志执行,相当于关闭了日志
  • ALL - 当日志界别为ALL时,对应的级别为 Integer.MIN_VALUE ,此时所有的日志都会执行
  • SEVERE - 错误信息 , 输出会导致程序终止的错误信息
  • WARNING - 警告信息 , 输出异常信息,不会使程序终止,但也需要注意
  • CONFIG - 配置信息,输出配置文件的加载和读取消息等
  • FINEFINERFINEST - DeBug 日志,记录程序的运行状态、执行流程、参数传递过程等,从FINE 到 FINEST ,记录的越来越详细

JUC 配置文件

默认配置文件

如果用户不做配置,那么JUC默认会读取 jre 文件 lib 目录下的 logging.properties 配置文件

在该配置文件中,我们可以看到 默认使用的执行器是 ConsoleHandler ,向控制台输出日志信息

而且制定了 level 为 INFO

下面是完整的配置文件信息(删除了所有的注释),可以看到除了 ConsoleHandler ,还配置了另外一个执行器 FileHandler 的信息,只不过 handlers= java.util.logging.ConsoleHandler 中只设置了ConsoleHandler 而没有设置 FileHandler,

handlers= java.util.logging.ConsoleHandler

.level= INFO

java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

com.xyz.foo.level = SEVERE

自定义配置文件

默认控制台输出,现在我们自定义配置文件,将日志信息输出到指定的日志文件中,并把日志级别改为ALL

修改后的 logging.properties 配置文件 如下:

handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler

.level= ALL

## 文件处理器
# 输出日志级别
java.util.logging.FileHandler.level=ALL
# 输出日志文件路径
java.util.logging.FileHandler.pattern = D:/JULlogs/java%u.log
# 输出日志文件限制大小(50000字节)
java.util.logging.FileHandler.limit = 50000
# 输出日志文件限制个数
java.util.logging.FileHandler.count = 1
# 输出日志格式
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

## 控制台处理器
# 输出日志级别
java.util.logging.ConsoleHandler.level = ALL
# 输出日志格式
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
  • 改变了handlers,添加了 java.util.logging.FileHandler ,将配置文件读取到日志文件中
  • 改变了.level ,将日志等级改为 ALL
  • 改变了 java.util.logging.FileHandler.pattern , 指定了日志文件的文件名和生成位置

其中 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter 指定了生成的日志文件为XML格式

我们将配置文件放到 SpringBoot下的 resources 文件下

编写一个测试类,代码如下:

public class JULTest {
   

    @Test
    public void test01() throws IOException {
   
        // 读取自定义配置文件
        InputStream in = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");
        // 获取日志管理器对象
        LogManager logManager = LogManager.getLogManager();
        // 通过日志管理器加载配置文件
        logManager.readConfiguration(in);
        Logger logger = Logger.getLogger("JULTest");
        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
    }

}

控制台打印结果:

去到指定的 D:/JULlogs 文件下,发现一个 java0.log 文件,内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>2023-08-12T14:31:36</date>
  <millis>1691821896349</millis>
  <sequence>0</sequence>
  <logger>JULTest</logger>
  <level>SEVERE</level>
  <class>com.zhuyuanjie.springbootproject.test.JULTest</class>
  <method>test01</method>
  <thread>1</thread>
  <message>severe</message>
</record>
<record>
  <date>2023-08-12T14:31:36</date>
  <millis>1691821896373</millis>
  <sequence>1</sequence>
  <logger>JULTest</logger>
  <level>WARNING</level>
  <class>com.zhuyuanjie.springbootproject.test.JULTest</class>
  <method>test01</method>
  <thread>1</thread>
  <message>warning</message>
</record>
<record>
  <date>2023-08-12T14:31:36</date>
  <millis>1691821896374</millis>
  <sequence>2</sequence>
  <logger>JULTest</logger>
  <level>INFO</level>
  <class>com.zhuyuanjie.springbootproject.test.JULTest</class>
  <method>test01</method>
  <thread>1</thread>
  <message>info</message>
</record>
<record>
  <date>2023-08-12T14:31:36</date>
  <millis>1691821896375</millis>
  <sequence>3</sequence>
  <logger>JULTest</logger>
  <level>CONFIG</level>
  <class>com.zhuyuanjie.springbootproject.test.JULTest</class>
  <method>test01</method>
  <thread>1</thread>
  <message>config</message>
</record>
<record>
  <date>2023-08-12T14:31:36</date>
  <millis>1691821896376</millis>
  <sequence>4</sequence>
  <logger>JULTest</logger>
  <level>FINE</level>
  <class>com.zhuyuanjie.springbootproject.test.JULTest</class>
  <method>test01</method>
  <thread>1</thread>
  <message>fine</message>
</record>
<record>
  <date>2023-08-12T14:31:36</date>
  <millis>1691821896376</millis>
  <sequence>5</sequence>
  <logger>JULTest</logger>
  <level>FINER</level>
  <class>com.zhuyuanjie.springbootproject.test.JULTest</class>
  <method>test01</method>
  <thread>1</thread>
  <message>finer</message>
</record>
<record>
  <date>2023-08-12T14:31:36</date>
  <millis>1691821896377</millis>
  <sequence>6</sequence>
  <logger>JULTest</logger>
  <level>FINEST</level>
  <class>com.zhuyuanjie.springbootproject.test.JULTest</class>
  <method>test01</method>
  <thread>1</thread>
  <message>finest</message>
</record>
</log>

当前日志文件采用覆盖方式,如果想使用追加方式,在配置文件中添加
java.util.logging.FileHandler.append=true

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
8月前
|
人工智能 Java 开发者
阿里出手!Java 开发者狂喜!开源 AI Agent 框架 JManus 来了,初次见面就心动~
JManus是阿里开源的Java版OpenManus,基于Spring AI Alibaba框架,助力Java开发者便捷应用AI技术。支持多Agent框架、网页配置、MCP协议及PLAN-ACT模式,可集成多模型,适配阿里云百炼平台与本地ollama。提供Docker与源码部署方式,具备无限上下文处理能力,适用于复杂AI场景。当前仍在完善模型配置等功能,欢迎参与开源共建。
3016 58
阿里出手!Java 开发者狂喜!开源 AI Agent 框架 JManus 来了,初次见面就心动~
|
11月前
|
自然语言处理 前端开发 Java
JBoltAI 框架完整实操案例 在 Java 生态中快速构建大模型应用全流程实战指南
本案例基于JBoltAI框架,展示如何快速构建Java生态中的大模型应用——智能客服系统。系统面向电商平台,具备自动回答常见问题、意图识别、多轮对话理解及复杂问题转接人工等功能。采用Spring Boot+JBoltAI架构,集成向量数据库与大模型(如文心一言或通义千问)。内容涵盖需求分析、环境搭建、代码实现(知识库管理、核心服务、REST API)、前端界面开发及部署测试全流程,助你高效掌握大模型应用开发。
996 5
|
7月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
7月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
619 8
|
7月前
|
存储 安全 Java
《数据之美》:Java集合框架全景解析
Java集合框架是数据管理的核心工具,涵盖List、Set、Map等体系,提供丰富接口与实现类,支持高效的数据操作与算法处理。
|
7月前
|
存储 算法 安全
Java集合框架:理解类型多样性与限制
总之,在 Java 题材中正确地应对多样化与约束条件要求开发人员深入理解面向对象原则、范式编程思想以及JVM工作机理等核心知识点。通过精心设计与周密规划能够有效地利用 Java 高级特征打造出既健壮又灵活易维护系统软件产品。
200 7
|
9月前
|
存储 缓存 安全
Java集合框架(二):Set接口与哈希表原理
本文深入解析Java中Set集合的工作原理及其实现机制,涵盖HashSet、LinkedHashSet和TreeSet三大实现类。从Set接口的特性出发,对比List理解去重机制,并详解哈希表原理、hashCode与equals方法的作用。进一步剖析HashSet的底层HashMap实现、LinkedHashSet的双向链表维护顺序特性,以及TreeSet基于红黑树的排序功能。文章还包含性能对比、自定义对象去重、集合运算实战和线程安全方案,帮助读者全面掌握Set的应用与选择策略。
1025 23
|
8月前
|
SQL Java 数据库连接
区分iBatis与MyBatis:两个Java数据库框架的比较
总结起来:虽然从技术角度看,iBATIS已经停止更新但仍然可用;然而考虑到长期项目健康度及未来可能需求变化情况下MYBATISS无疑会是一个更佳选择因其具备良好生命周期管理机制同时也因为社区力量背书确保问题修复新特征添加速度快捷有效.
725 12