尝试JUT
JDK自带的日志系统也就是JUT,如果我们一直用System.out.println()来在控制台输出信息的话,我们有时候还得找这个东西在哪,如果调试算法题的话应该深有体会。那么Java自己就有一个类java.util.logging包下,实现日志打印:
1 | public class Main { |
5月 21, 2026 9:40:20 下午 test.main main
信息: 我是普通的日志
我们可以看到日志打印出来的效果会更完善。
日志等级
日志分为7个级别,详细信息我们可以在Level类中查看:
- SEVERE(最高值)- 一般用于代表严重错误
- WARNING - 一般用于表示某些警告,但是不足以判断为错误
- INFO (默认级别) - 常规消息
- CONFIG
- FINE
- FINER
- FINEST(最低值)
我们之前用的就是logger.info,但其实我们可以logger.log(Level.等级,"内容")来实现:
1 | public static void main(String[] args) { |
5月 21, 2026 9:46:18 下午 test.main main
严重: 严重的错误
java.io.IOException: 我就是错误
at test.main.main(main.java:18)
5月 21, 2026 9:46:18 下午 test.main main
警告: 警告的内容
5月 21, 2026 9:46:18 下午 test.main main
信息: 普通的信息
我们会发现INFO等级下面的不会输出到控制台,这是因为日志还有打印机别,打印机别同样也是可控的,我们来修改一下:
1 | public static void main(String[] args) { |
这里需要讲解一下:
- 我们设置了日志等级,意思就是可以打印大于等于这个等级的
- 我们不是用付日默认父日志器(根日志器)级别是 INFO,比 CONFIG 高,会挡住 CONFIG。我们关掉它,就不再受默认限制。
- 设置处理器 ConsoleHandler 级别 = CONFIG处理器负责真正输出。它也只输出 ≥ CONFIG 的日志。
5月 21, 2026 9:52:34 下午 test.main main
严重: 严重的错误
java.io.IOException: 我就是错误
at test.main.main(main.java:29)
5月 21, 2026 9:52:35 下午 test.main main
警告: 警告的内容
5月 21, 2026 9:52:35 下午 test.main main
信息: 普通的信息
5月 21, 2026 9:52:35 下午 test.main main
配置: 级别低于普通信息
文件日志处理器
我们通过使用自己日志处理器来自定义级别的信息打印到控制台,当然,日志处理器不仅仅只有控制台打印,我们也可以使用文件处理器来处理日志信息,我们继续添加一个处理器:
1 | //添加输出到本地文件 |
这个时候我们有两个日志处理器,都会生效,不过这个时候打印出来的文件,我们会发现里面的格式不太一样,那是因为它默认的格式是xml。我们还可以自定义打印格式,比如我们控制台处理器就默认使用的是SimpleFormatter,而文件处理器则是使用的XMLFormatter,我们可以自定义:
1 | //使用自定义日志处理器(控制台) |
同样的我们也可以把控制台的改成XML类型的,不过这里就自行查询把。可是我们现在又有一个问题,打印出的文件内容会覆盖,这样才能不覆盖往后追加呢?
1 | FileHandler fileHandler = new FileHandler("test.log",true); |
这样就好了。
我们可以直接配置为想要的打印格式,如果这些格式还不能满足你,那么我们也可以自行实现:
1 | public static void main(String[] args) throws IOException { |
过滤器
日志可以设置过滤器,如果我们不希望某些日志信息被输出,我们可以配置过滤规则:
1 | public static void main(String[] args) throws IOException { |
这里setFilter中放入的是接口实现类,所以我们这样写,那么只有带有普通的消息会打印出来。

流程是这个样子的,我们刚才写的是Logger这里的过滤器,在处理器中我们也可以塞过滤器。
Properties配置文件
我们之前解析过XML文件,就和我们学的Python爬虫一样,最后转换为树,其实挺麻烦的。那么Java自带一种配置文件格式为Properties的,读取起来很简单,格式如下:
1 | name=Test |
这其实本身类似于一个map,这个name就是key,而desc就是value。
1 | public static void main(String[] args) throws IOException { |
这里输出和map差不多,并且Properties本身就继承于哈希表,而哈希表又和map结构差不多。我们也可以往里面put一些东西打印出来,但并不会放入文件(注意value不能为空,而map可以,还是有点不同的)。
1 | public static void main(String[] args) throws IOException { |
- 只用
put,不调用 store/storeToXML:只在内存里,不会写到文件 / 控制台 - 调用
store:内存里所有数据全部持久化输出
但如果:
1 | properties.store(new FileOutputStream("test.properties"), "注释"); |
就会了。
编写日志配置文件
我们可以在properties文件中放我们JUT的日志配置文件:
1 | # RootLogger 的默认处理器为 |
- RootLogger = 你家祖宗
- 你的 Logger = 你
- 祖宗设置 级别 = CONFIG
我们来尝试使用配置文件来进行配置:
1 | public static void main(String[] args) throws IOException { |
你可以把 LogManager 理解成:日志的总控制器
- 整个 JVM 里只有一个
- 所有 Logger 都是它 “生” 出来的
- 你给它读配置文件 = 给整个日志系统统一设置
我们也可以去修改ConsoleHandler的默认配置:
1 | # 指定默认日志级别 |
- 日志能输出 CONFIG 级别
- 控制台输出 不拦截任何日志
- 中文不乱码
- 格式干净整洁
使用Lombok快捷使用log
Logger也是可以使用Lombok快速生成的:
1 |
|
这里的log是一个静态成员变量,我们也可以手动指定名称:
1 |
|
Mybatis日志系统
我们需要在Mybatis配置文件设置中写入以下命令:
1 | <setting name="logImpl" value="STDOUT_LOGGING" /> |
logImpl包括很多种配置项,包括 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING,而默认情况下是未配置,也就是说不打印。我们这里将其设定为STDOUT_LOGGING表示直接使用标准输出将日志信息打印到控制台,我们编写一个测试案例来看看效果:
1 | public class TestMain { |
我们发现,两次获取学生信息,只有第一次打开了数据库连接,而第二次并没有。
现在我们学习了JUT日志系统,那么我们来尝试使用JUT日志系统输出Mybatis的日志信息:
1 | <setting name="logImpl" value="JDK_LOGGING" /> |
将其配置为JDK_LOGGING表示使用JUL进行日志打印,因为Mybatis的日志级别都比较低,因此我们需要设置一下logging.properties默认的日志级别:
1 | handlers= java.util.logging.ConsoleHandler |
Java代码如下:
1 |
|
但是我们发现,这样的日志信息根本没法看,因此我们需要修改一下日志的打印格式,我们自己创建一个格式化类:
1 | public class TestFormatter extends Formatter { |
现在再来修改一下默认的格式化实现:
1 | handlers= java.util.logging.ConsoleHandler |
现在就好看多了。
代码回顾
运行
1 | log.info(mapper.getStudentBySidAndSex(1, "男").toString()); |
第一步:执行 mapper.getStudentBySidAndSex(...)
这里触发 MyBatis 执行 SQL
👉 控制台先输出:MyBatis 的 SQL 日志
1 | ==> Preparing: select * from student where sid=? and sex=? |
第二步:拿到 Student 对象,调用 .toString()
拿到字符串:Student{sid=1,name=张三,sex=男}
第三步:执行 log.info(...)
👉 控制台再输出:你自己的 java.util.logging 日志
1 | 五月 22, 2025 15:30:00 com.TestMain test |
我们会发现第二个根本没有SQL日志输出,因为从缓存调用了。
说些什么吧!