log.info中使用多个占位符{}问题

在 Java 中使用 log.info()(如 SLF4J、Logback、Log4j2 等日志框架)时,多个占位符 {} 的使用非常常见且安全,但需要注意以下几点以避免常见错误。

java 复制代码
//正确用法:多个 {} 按顺序匹配参数

log.info("用户 {} 在 {} 执行了操作 {}, 耗时 {} ms", userId, timestamp, action, duration);

//问题 1:想输出字面量 {},但被当作占位符
log.info("配置项 {{timeout}} = {}", timeout); 
// 期望输出:{timeout} = 5000
// 实际输出:{timeout = 5000  (左花括号被吃掉!)

//解决:用双大括号 {{}} 转义:
log.info("配置项 {{timeout}} = {}", timeout); 
// 输出:{timeout} = 5000 


//问题 2:参数为 null 或复杂对象,输出不友好
log.info("请求参数: {}", requestObject); 
// 可能输出:com.xxx.Request@1a2b3c(默认 toString)
//使用 JSON 序列化(如 Jackson):
log.info("请求参数: {}", JSON.toJSONString(requestObject));


//问题 3:异常信息未正确传递
// 错误:异常作为普通参数,不会打印堆栈
log.info("处理失败: {}", e); 

// 正确:异常必须放在**最后一个参数**,且不要用 {}
log.info("处理失败", e); 
// 或
log.info("用户 {} 处理失败", userId, e); // e 是最后一个参数
//规则:只有当最后一个参数是 Throwable 时,日志框架才会打印堆栈跟踪。



// SLF4J 不支持{0}, {1} 这种格式(那是 MessageFormat 的语法)!
// ❌ 错误!SLF4J 会原样输出 "{0}"
log.info("用户 {0} 操作 {1}", userId, action); 
    

最佳实践总结

示例:完整正确用法

java 复制代码
String userId = "U1001";
String action = "支付";
long duration = 125L;
Exception ex = new RuntimeException("网络超时");

// 正常多参数
log.info("用户 {} 执行 {} 耗时 {}ms", userId, action, duration);

// 带异常(ex 必须是最后一个)
log.info("用户 {} 操作失败", userId, ex);

// 输出字面 {}
log.info("JSON 模板: {{\"user\": \"{}\"}}", userId);
// 输出:JSON 模板: {"user": "U1001"}
相关推荐
kimnoic15 小时前
Python数据库学习心得:SQLite、MySQL、PostgreSQL优缺点
开发语言·python
必须得开心呀16 小时前
python编写带界面的软件,需要安装哪些插件
开发语言·python
沫璃染墨18 小时前
《Qt从零入门系列(十三):QSS样式表详解——从选择器与层叠规则到控件美化实战》
开发语言·css·c++·qt·ui·qt6.3·qss
达子66618 小时前
RUST 图解 第 3 章:通用编程概念(Common Programming Concepts)
开发语言·算法·rust
道尔柯南19 小时前
C++ 面向对象编程入门:类和对象(上)
开发语言·c++·算法
楠楠子呀19 小时前
英语、西语、阿语客户各开一个口:多语言获客的分流方案
开发语言·javascript·ecmascript·跨境电商·whatsapp·营销工具
tachibana219 小时前
使用for range 的时候,它的地址会发生变化吗?
开发语言·后端·golang·go·语法
临床数据科学和人工智能兴趣组20 小时前
正则表达式的基础语法的基本符号
开发语言·人工智能·python·正则表达式·r语言·r语言-4.2.1·workbudyy
王中阳Go20 小时前
Go 后端转 AI:非科班怎么补?一张 3 列路线表(可保存)
开发语言·人工智能·后端·python·golang·大语言模型
geats人山人海20 小时前
java 4继承
java·开发语言