Java日志打印的6个高质量方法:反例 + 正例,告别无效日志

SpringBoot单元测试实战:JUnit5与Mockito构建高质量代码保障体系 单元测试作为软件质量保障的核心环节,通过隔离测试单个代码单元来验证其逻辑正确性。其原理在于模拟外部依赖,聚焦被测对象行为,确保代码变更不会引入回归缺陷。在工程实践中,单元测试能显著提升代码可维护性,降低缺陷修复成本,并为持续重构提供安全网。尤其在微服务与分布式架构盛行的当下,单元测试成为保障服务稳定性的基础手段。本文以SpringBoot项目为背景,深入讲解如何运用JUnit5进行生命周期管理、参数化测试,并结合Mockito实现依赖模拟与行为验证,通过实战演示如何构建高效可靠的测试套件,并合理运用测试覆盖 阅读详情

为什么你的日志总是“食之无味”?

日志是Java程序排查问题的“生命线”,但很多开发者的日志总是打不到重点,无法精准定位问题,今天我们来聊聊如何几个高质量日志打印方法

前提

建议使用统一的日志框架SLF4J + Logback/Log4j2

// 正确引入(类顶部)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OrderService {
    // 静态常量,避免每次创建Logger实例
    private static final Logger log = LoggerFactory.getLogger(OrderService.class);
}

1.参数完整

  • 反例:只说 “失败了”,要说清 “为什么失败”

log.info("用户登录失败");

哪个用户失败了?在何时?失败原因是什么?

  • 核心原则:日志必须包含「上下文 + 参数 + 异常信息」

  • 正例:

log.warn("用户登录失败 name={}, IP={}, time={}, failReason={}", 
    username, clientIP, new Date(),"密码错误");

2.日志级别使用不当

  • 反例:级别滥用

// 反例1:调试信息用INFO,生产环境日志刷屏
log.info("订单查询参数:orderId={}", 123456);

// 反例2:致命异常用WARN,易被忽略
log.warn("数据库连接失败,无法创建订单");

// 反例3:ERROR打印非异常信息(如正常流程)
log.error("订单创建成功,orderId={}", 123456);
  • 核心原则:日志级别按 “从细到粗” 分为 TRACE < DEBUG < INFO < WARN < ERROR。

  • 级别定义表:

级别

适用场景

TRACE

极细粒度的调试信息(如框架内部流程)

DEBUG

开发/测试环境的调试信息(如参数、执行步骤)

INFO

生产环境核心流程(如服务启动、订单创建成功)

WARN

非致命异常(如参数不合法、资源不足)

ERROR

致命异常(如调用第三方接口失败、数据库连接异常)

  • 正例

// DEBUG:开发环境调试,生产可关闭
log.debug("订单查询参数:orderId={}", 123456);

// INFO:核心业务流程,生产必打
log.info("订单创建成功,orderId={},用户ID={}", 123456, 789);

// WARN:非致命问题,需关注但不阻断流程
log.warn("订单参数不合法:userId={},原因:{}", 789, "用户ID为空");

// ERROR:致命异常,必须包含异常栈+上下文
try {
    createOrder();
} catch (SQLException e) {
    log.error("创建订单失败,orderId={}", 123456, e);
}

3.异常必须打印堆栈

  • 反例

// 反例1:仅打印异常信息,丢失栈
try {
    orderDao.insert(order);
} catch (SQLException e) {
    log.error("插入订单失败:{}", e.getMessage());
}

// 反例2:重复打印异常栈
try {
    orderDao.insert(order);
} catch (SQLException e) {
    log.error("插入订单失败", e);
    throw new BusinessException("插入失败", e); // 上层又打印一次,日志冗余
}
  • 核心原则:异常日志必须传递Throwable对象

  • 正例

// 正例1:打印完整异常栈
try {
    orderDao.insert(order);
} catch (SQLException e) {
    log.error("插入订单失败,订单ID={}", order.getId(), e);
    // 若需要抛上层,无需重复打印,上层统一处理
    thrownew BusinessException("插入订单失败", e);
}

// 正例2:吞异常时必须打日志
try {
    thirdService.sendMsg(userId, msg);
} catch (Exception e) {
    // 允许消息发送失败,但必须记录日志
    log.warn("消息发送失败,用户ID={},消息内容={}", userId, msg, e);
}
4.敏感信息泄露

打印日志泄露用户手机号有可能被投诉

  • 反例

// 反例1:打印完整手机号/身份证
log.info("用户登录,手机号={},身份证={}", "13812345678", "110101199001011234");

// 反例2:打印密码/令牌
log.debug("调用第三方接口,token={},密码={}", "admin_edfojofwog", "123456");
  • 核心原则:用户手机号、身份证、密码、银行卡号等敏感信息,脱敏后再打印

  • 正例

// 工具方法:手机号脱敏(138****5678)
private static String maskPhone(String phone) {
    if (phone == null || phone.length() != 11) {
        return phone;
    }
    return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
}

// 工具方法:身份证脱敏(110101********1234)
private static String maskIdCard(String idCard) {
    if (idCard == null || idCard.length() != 18) {
        return idCard;
    }
    return idCard.replaceAll("(\\d{6})\\d{8}(\\d{4})", "$1********$2");
}
// 正例:打印脱敏后的信息
log.info("用户登录,手机号={},身份证={}", maskPhone("13812345678"), maskIdCard("110101199001011234"));
log.debug("调用第三方接口,token={}", "******");

5.占位符的正确打开方式

  • 反例

log.info("User:" + user.getId() + " username " + user.getName());
  • 核心原则:别用 “+”,避免性能损耗

  • 正例

log.info("User:{} username {}", user.getId(), user.getName());

6.MDC链路追踪

MDC.put("traceId", UUID.randomUUID().toString().substring(0,8));

//logback.xml配置
<pattern>%d{yyyy-MM-dd} [%X{traceId}] %-5level %logger{36} - %msg%n</pattern>
  • 核心原则:多个服务调用可以通过traceId全联路追踪

  • 输出结果

输出效果: 2026-01-13 [e44d4gae-6kk4-3er4-rr4t-t0ykyreg] INFO com.example.OrderService - 下单成功

往期文章回顾

Redis 有一亿个key,如何优雅捞出 10 万条前缀 Key 的实战方案

@Transactional 本质是 AOP,事务失效就看这 1 点

Java 8 都老了,Optional 为啥还是没人用?到底卡在哪了?

Codex代码生成实战:统计模型的边界与工程化落地方法 代码生成模型(如OpenAI Codex)本质上是基于海量代码训练的统计语言模型,而非具备逻辑推理能力的编程引擎。其核心原理是依据上下文预测高概率token序列,因此在模式复刻类任务(如日志解析、模板化测试用例)中表现优异,但在需深层语义理解的场景(如跨数据库迁移、安全敏感逻辑)易产生‘合理幻觉’。技术价值在于提升重复性编码效率,降低启动门槛;典型应用场景包括中后台系统胶水代码生成、单元测试补全、API适配器开发等。本文聚焦真实交付环境下的效能评估、幻觉识别与CI/CD嵌入式治理,揭示如何将Codex从‘不 阅读详情

相关推荐

.NET技术博客的底层逻辑:从人到程序员的能力跃迁

编程能力不是线性堆叠的语法与框架,而是以‘人’为起点的立体成长体系。在真实工程场景中,沟通表达、需求澄清、协作判断等非技术能力,往往比代码实现更能决定项目成败;而.NET生态因其企业级稳定性与微软长期支持,成为验证这类能力的理想技术载体。本文聚焦1–5年经验开发者的核心痛点——如何在复杂需求、模糊文档与线上事故中做出可靠决策,通过真实案例拆解‘做人→技术人员→程序员’三层能力模型,揭示技术深度的本质不在参数罗列,而在约束条件下的权衡与验证。内容覆盖.NET 8容器化GC调优、EF Core生产迁移陷阱、Bl

diaoqi6581的博客 498

打印高质量日志大10条军规

这篇文章跟大家一起聊聊打印优质日志的10条军规,希望对你会有所帮助。更多项目实战在我的技术网站:www.susan.net.cn/project研发人员的三大境界青铜")钻石:标准化日志 + ELK监控王者日志驱动代码优化异常预测系统根因分析AI模型最后的灵魂拷问下次线上故障时,你的日志能让新人5分钟定位问题吗?更多项目实战在我的技术网站:www.susan.net.cn/project。

1366

Dense Passage Retriever(DPR)实战指南:从原理到千万级知识库部署

稠密检索(Dense Retrieval)是现代RAG系统的核心基础,它通过将查询与文本段落映射至统一语义向量空间,突破传统关键词匹配的词汇鸿沟与语义歧义瓶颈。其核心原理在于对比学习驱动的双塔编码架构,以负采样机制强化模型对‘真相关’与‘伪相关’的判别能力,从而在毫秒级完成高精度段落召回。该技术显著提升企业知识库、智能客服与故障诊断等场景下的首召回率与用户满意度,尤其适用于需低延迟、高准确率的私有化语义检索任务。本文聚焦Dense Passage Retriever(DPR)的工程落地全过程。

turnRound 485

打印高质量日志的10条军规

研发人员的三大境界青铜")钻石:标准化日志 + ELK监控王者:日志驱动代码优化异常预测系统根因分析AI模型最后的灵魂拷问:下次线上故障时,你的日志能让新人5分钟定位问题吗?苏三说技术from=001YH。

kfashfasf的博客 653

别再只会用Excel了!Minitab 21手把手教你搞定SPC控制图(从数据导入到结果解读)

本文详细介绍了如何使用Minitab 21高效制作SPC控制图,从数据导入到结果解读的全流程。通过对比Excel的局限性,展示Minitab在自动化计算、图表标准化和特殊原因检验等方面的优势,帮助质量管理人员提升工作效率和数据分析专业性。

weixin_30878501的博客 380

DAIC-WOZ抑郁数据集实战:从申请到特征提取的全流程避坑指南

本文详细解析了DAIC-WOZ抑郁数据集从申请到特征提取的全流程,提供了实用的避坑指南和代码模板。涵盖数据获取技巧、多模态特征工程(面部动作单元、音频特征、文本处理)以及样本不平衡解决方案,帮助研究者高效处理这一经典抑郁分析数据集。

weixin_29196315的博客 170

别在 Java 代码里乱打日志了,这才是打印日志的正确姿势!

作者:西格玛的博客来源:http://lrwinx.github.io/使用slf4j使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。实现方式统一使用: Logback框架打...

程序员闪充宝 106

FastAPI + React:现代 Web 前后端分离开发的全栈实践指南

• 部署:CI/CD 双流水线,前端 push → GitHub Actions → Cloudflare Pages;• 后端:分层结构 routers → services → repositories → models,单测覆盖率 90 %。• 接口缓存:Redis + FastAPI Depends 实现接口级缓存,读 QPS 提升至 5 k。• 前端:BFF 由 React Query 代理,统一缓存、重试、分页。GET /items/{id} 详情。,前端同学无需等 Mock 即可联调。

未来已来,AI时代,学AI编程,做AI量化,就来大鹏AI教育。 1490

瞧瞧别人家的日志打印,那叫一个优雅!

后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,上面的日志拼接成了一个字符串,虽说中间有空格分隔了,但哪些字段对应了哪些值,看起来不是很清楚。登录失败的业务场景,需要记录哪个用户,ip是多少,在什么时间,登录失败了,失败的原因是什么。

犬小哈 109

告别环境配置焦虑:在Win10的Ubuntu子系统里搞定CSAPP实验环境(附32/64位库编译指南)

本文详细介绍了如何在Win10的Ubuntu子系统中搭建CSAPP实验环境,包括WSL 2的安装与配置、32/64位库的编译指南以及高效开发工具链的设置。通过优化WSL性能和使用实用技巧,开发者可以轻松应对CSAPP实验中的环境配置问题,提升学习效率。

weixin_30443813的博客 296

LPDDR5时序精调:深入解析Read Gate Training的两种模式

本文深入解析了LPDDR5内存中关键的Read Gate Training技术,详细对比了RDQS Toggle Mode(翻转模式)与Enhanced RDQS Mode(增强模式)的工作原理、时序参数及适用场景。文章阐述了在高速数据传输下精准校准时序的必要性,并提供了两种模式的实战选型指南与系统级调试思路,帮助工程师优化内存性能与稳定性。

weixin_29219189的博客 365

打印优质日志的 10 条军规

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。

芋艿V 75

西门子博图TIA Portal V18实战:用LAD梯形图快速上手一个电机启停控制程序

本文详细介绍了如何在西门子博图TIA Portal V18中使用LAD梯形图快速实现电机启停控制程序。从项目创建、硬件组态到LAD编程和仿真调试,逐步引导读者掌握PLC编程的核心逻辑,特别适合工业自动化领域的初学者快速上手。

weixin_30617737的博客 689

别在 Java 代码里乱打日志了,这才是正确的打日志姿势

关注“Java后端技术栈”回复“面试”获取最新资料回复“加群”邀您进技术交流群使用slf4j使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。实现方式统一使用: Logbac...

田维常 363

conda环境的复制、备份操作

请确保将 source_env 替换为你要复制的现有环境的名称,并将 target_env 替换为你要创建的新环境的名称。要备份一个Conda虚拟环境,你需要将环境的配置信息和依赖包列表保存起来,以便在需要的时候能够重新创建相同的环境。要将现有的 conda 环境复制为其他环境,可以使用 conda create 命令并克隆已存在的环境。

Dollhan的博客 3771

【Jenkins】Jenkins :首次登录直接使用 admin 账户

目录 一、使用admin账户 二、修改admin用户密码 三、管理视图 一、使用admin账户 安装时,自定义安装,选择必要的插件安装,设置Jenkins的URL为: http://本机或服务器IP:8080 然后在创建第一个管理者界面,直接选择:使用admin 二、修改admin用户密码 进入:系统管理——管理用户——选中用户——点击设置图标——修改密码: 三、...

顾三殇 —— 博客空间(软件测试) 1万+

java后端好习惯---新手养成记

本文总结了15个提升代码质量的开发好习惯:1.全面注释(类/方法/复杂逻辑);2.参数≥3时封装对象;3.封装通用模板方法避免重复代码;4.封装复杂判断逻辑;5.善用工具类;6.规范日志打印(入口/出口/异常);7.统一异常处理;8.合理项目目录结构;9.浮点数用BigDecimal比较;10.包装类用equals比较;11.日期格式化注意事项;12.集合操作规范(判空/toMap/subList等);13.预防运行时错误(越界/除零/空指针);14.finally释放资源;15.控制方法复杂度(≤80行)

weixin_57259781的博客 1635

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

面向日志语义化与统一追踪上下文的互联网系统诊断设计思路与多语言工程实践分享

日志是系统对外的“自述能力”上下文统一比日志格式更重要可诊断性是一种设计目标,而不是事后补救日志语义化与统一追踪上下文,并不是为了让系统“话更多”,而是为了让系统“说得清楚”。当系统能够持续、准确地描述自己正在做什么、为什么这么做、以及做到了哪一步,工程师才能在复杂环境中快速恢复对系统的理解。通过在多语言实现中统一上下文传播方式,在架构层面明确日志语义边界,日志才能真正从“文本输出”升级为“系统诊断能力”。

2501_94182049的博客 367

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Java异常处理成本:toBeBetterJavaer性能分析

在Java开发中,异常处理是保证程序健壮性的关键机制,但不恰当的异常使用会显著影响系统性能。本文基于[toBeBetterJavaer](https://link.gitcode.com/i/4254eee99694fb4f120e724412816d43)项目的实践经验,从异常捕获机制、性能损耗场景和优化策略三个维度,深入分析异常处理的隐性成本。 ## 异常处理的性能损耗原理 Java异常处

gitblog_00990的博客 347

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Android 代码风格规范

1. 项目指南 1.1 项目结构 新项目应该遵循安卓Gradle项目结构,定义在这里 :安卓Gradle插件用户指南。项目ribot Boilerplate 是一个很好的参考。 1.2 文件命名 1.2.1 类文件 类名书写方式是 大写的驼峰命名. 继承于安卓组件的类,名称应该以继承的组件命名,比如:SignInActivity, SignInFragment,

柳的博客 1984

GitHub上star超过2k的安卓项目和代码风格指南(绝对干货)

前几天看到的一个帖子,比较火,五一节没有时间开电脑,所以现在贴出来和大家分享一下。 转载地址:http://weizhan.51cto.com/article/view/58e5fe3bf2dd8763f472c5c1?is_share=1 注释:感谢原创作者和后期翻译者的辛苦。 近日在搜MVP模式作为安卓项目架构时候,发现GitHub上一篇介绍MVP架构的文章。一看star已经超过

RKGG爱吃鱼 1496

SOLID五大原则实战指南:从代码失控到工程可控

SOLID是面向对象软件设计的基础性工程原则,涵盖单一职责、开闭、里氏替换、接口隔离与依赖倒置五大核心概念。其本质并非抽象理论,而是应对‘改一处崩一片’等典型维护困境的防御性实践体系——通过识别变化原因实现职责收敛(SRP),用接口契约封装可变逻辑达成稳定扩展(OCP),以行为一致性保障继承安全(LSP),按客户端需求裁剪接口粒度(ISP),并借抽象层解耦高层与实现细节(DIP)。这些原则共同构成可测试、易演进、低耦合的系统架构基石,广泛适用于Java、C#、Python及TypeScript等主流语言的业

weixin_33805992的博客 438

.NET正则引擎深度解析:从NFA原理到平衡组实战

正则表达式本质是基于非确定性有限状态自动机(NFA)的文本处理机制,其核心在于控制权流转、回溯行为与零宽断言的协同。理解占有字符与零宽度的区别,是避免过度匹配和调试失效的前提;掌握贪婪/非贪婪量词背后的试探策略,可显著提升日志解析、配置校验等工程场景的稳定性。在.NET平台中,命名分组、条件分支与独有的平衡组语法,使正则具备了结构化提取嵌套内容的能力。本文聚焦真实项目中的性能瓶颈与失控案例,结合回溯可视化、占有量词优化及编译缓存等实践手段,系统构建面向生产环境的正则工程方法论。

diaoqi6581的博客 449
上一篇: 一行命令查看linux centos7外网公网地址
下一篇: 刚安装好的IDEA在插件库里面搜索不到要安装的插件
新时代Java农民工
博客等级 码龄7年 16粉丝 116原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值