【Java踩坑笔记】45_日志打印对象用toString,生产环境可能引发雪崩

📅 2026/7/15 20:22:11
【Java踩坑笔记】45_日志打印对象用toString,生产环境可能引发雪崩
45 | 日志打印对象用 toString生产环境可能引发雪崩摘要log.info(订单{}, order)会触发order.toString()如果toString()里拼接了大量字段或有循环引用生产环境高并发下会引发性能雪崩。一、问题现象// ❌ 危险直接打印整个对象log.info(处理订单{},order);// order.toString() 可能是publicStringtoString(){returnOrder{idid, userIduserId, itemsitems, logslogs...};// 如果 items 有 1000 条toString() 极其耗时}现象生产环境日志量暴增CPU 占用升高接口响应变慢。二、踩坑现场场景 1toString() 里有集合字段// ❌ 危险toString() 里打印了 ListToStringclassOrder{privateLongid;privateListOrderItemitems;// 可能 1000 条privateListOrderLoglogs;// 可能 500 条}log.info(订单{}, order)→ 触发order.toString()→ 拼接 1500 条子对象的toString()→ 一次日志耗时 500ms。场景 2敏感信息打印到日志// ❌ 危险用户密码、Token 打印到日志log.info(用户登录{},user);// user.toString() 包含 password三、正确写法3.1 只打印关键字段// ✅ 正确只打印关键字段log.info(处理订单orderId{}, userId{},order.getId(),order.getUserId());3.2 用 Lombok ToString 排除大字段// ✅ 正确排除大字段ToString(exclude{items,logs})classOrder{privateLongid;ToString.Exclude// Lombok 新版本privateListOrderItemitems;}3.3 敏感字段不打印// ✅ 正确敏感字段用 ToString.Exclude 排除ToStringclassUser{privateLongid;ToString.Exclude// 排除 passwordprivateStringpassword;privateStringname;}3.4 JSON 打印需控制深度// ✅ 需要打印对象时用 JSON 且排除敏感字段log.info(订单{},JsonUtils.toJson(order,password,token));四、最佳实践✅ 日志打印的 5 条铁律不要直接打印整个对象只打印关键字段ToString排除大字段和集合字段敏感字段password、token必须排除日志里不要用字符串拼接用占位符{}生产环境关闭 DEBUG 日志只开 INFO/WARN Lombok ToString 配置ToString(exclude{items,logs},// 排除字段callSuperfalse,// 不打印父类字段includeFieldNamestrue// 打印字段名)classOrder{...}五、小结log.info({}, obj)会触发obj.toString()如果toString()拼接大字段高并发下性能雪崩只打印关键字段不要直接打印整个对象ToString排除大字段和集合字段敏感字段必须排除防止泄露生产环境只开 INFO/WARN关闭 DEBUG下一篇预告用 switch 忘了写 breakJava 14 之后有更好的写法—— 穿透问题fall-through是 C 语言遗留的设计Java 14 的 switch 表达式彻底解决了它。更多资料一线大厂Java面试题合集