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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 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

相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
目录
相关文章
|
3月前
|
自然语言处理 前端开发 Java
JBoltAI 框架完整实操案例 在 Java 生态中快速构建大模型应用全流程实战指南
本案例基于JBoltAI框架,展示如何快速构建Java生态中的大模型应用——智能客服系统。系统面向电商平台,具备自动回答常见问题、意图识别、多轮对话理解及复杂问题转接人工等功能。采用Spring Boot+JBoltAI架构,集成向量数据库与大模型(如文心一言或通义千问)。内容涵盖需求分析、环境搭建、代码实现(知识库管理、核心服务、REST API)、前端界面开发及部署测试全流程,助你高效掌握大模型应用开发。
363 5
|
10月前
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
10月前
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
|
5月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
374 70
|
9月前
|
存储 安全 Java
Java 集合框架中的老炮与新秀:HashTable 和 HashMap 谁更胜一筹?
嗨,大家好,我是技术伙伴小米。今天通过讲故事的方式,详细介绍 Java 中 HashMap 和 HashTable 的区别。从版本、线程安全、null 值支持、性能及迭代器行为等方面对比,帮助你轻松应对面试中的经典问题。HashMap 更高效灵活,适合单线程或需手动处理线程安全的场景;HashTable 较古老,线程安全但性能不佳。现代项目推荐使用 ConcurrentHashMap。关注我的公众号“软件求生”,获取更多技术干货!
142 3
|
3月前
|
存储 安全 Java
现代应用场景中 Java 集合框架的核心技术与实践要点
本内容聚焦Java 17及最新技术趋势,通过实例解析Java集合框架的高级用法与性能优化。涵盖Record类简化数据模型、集合工厂方法创建不可变集合、HashMap初始容量调优、ConcurrentHashMap高效并发处理、Stream API复杂数据操作与并行流、TreeMap自定义排序等核心知识点。同时引入JMH微基准测试与VisualVM工具分析性能,总结现代集合框架最佳实践,如泛型使用、合适集合类型选择及线程安全策略。结合实际案例,助你深入掌握Java集合框架的高效应用与优化技巧。
120 4
|
10月前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
492 3
|
6月前
|
机器学习/深度学习 人工智能 Java
Java机器学习实战:基于DJL框架的手写数字识别全解析
在人工智能蓬勃发展的今天,Python凭借丰富的生态库(如TensorFlow、PyTorch)成为AI开发的首选语言。但Java作为企业级应用的基石,其在生产环境部署、性能优化和工程化方面的优势不容忽视。DJL(Deep Java Library)的出现完美填补了Java在深度学习领域的空白,它提供了一套统一的API,允许开发者无缝对接主流深度学习框架,将AI模型高效部署到Java生态中。本文将通过手写数字识别的完整流程,深入解析DJL框架的核心机制与应用实践。
353 3
|
7月前
|
存储 缓存 Java
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
731 3
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
|
5月前
|
存储 安全 Java
Java 集合框架详解:系统化分析与高级应用
本文深入解析Java集合框架,涵盖List、Set、Map等核心接口及其常见实现类,如ArrayList、HashSet、HashMap等。通过对比不同集合类型的特性与应用场景,帮助开发者选择最优方案。同时介绍Iterator迭代机制、Collections工具类及Stream API等高级功能,提升代码效率与可维护性。适合初学者与进阶开发者系统学习与实践。
168 0