Log4j2编程式JdbcAppender的ColumnConfig Lookup无法生效
问题分析与解决方案
你的问题核心有两个:
- 数组越界导致列配置失效:原代码中
ColumnConfig数组长度仅为5,却尝试给索引8赋值,这会触发数组越界异常,导致username列的配置根本无法被应用。 - Pattern表达式格式错误:编程式配置无需经过Log4j配置文件的预解析流程,直接使用
$${app:username}会被PatternLayout解析为字面量${app:username},而非触发自定义Lookup插件。
修复步骤
1. 修正数组长度与索引
根据实际需要的列数调整ColumnConfig数组长度,并使用合法的索引赋值:
// 调整数组长度为6(对应0-5共6列) ColumnConfig[] columnConfigs = new ColumnConfig[6]; // 保持logger、level、message、exception、revision_id的配置不变 columnConfigs[0] = ColumnConfig.newBuilder() .setName("logger") .setPattern("%logger") .setUnicode(false) .build(); columnConfigs[1] = ColumnConfig.newBuilder() .setName("level") .setPattern("%level") .setUnicode(false) .build(); columnConfigs[2] = ColumnConfig.newBuilder() .setName("message") .setPattern("%message") .setUnicode(false) .build(); columnConfigs[3] = ColumnConfig.newBuilder() .setName("exception") .setPattern("%ex{full}") .setUnicode(false) .build(); columnConfigs[4] = ColumnConfig.newBuilder() .setName("revision_id") .setPattern("%X{rev.id}") .setUnicode(false) .build(); // 使用合法索引5配置username列,并修正Pattern columnConfigs[5] = ColumnConfig.newBuilder() .setName("username") .setPattern("${app:username}") // 移除多余的$符号 .setUnicode(false) .build();
2. 验证Appender配置
确保JdbcAppender启动后被正确添加到RootLogger:
appender.start(); Logger logger = (Logger) LogManager.getRootLogger(); // 可先检查是否已存在同名Appender,避免重复添加 if (logger.getAppender("Database") == null) { logger.addAppender(appender); }
原理说明
- 在XML配置中,
$${app:username}是为了避免Log4j配置文件预解析${app:username},最终会被转换为${app:username}传递给PatternLayout。 - 编程式配置直接将Pattern传递给ColumnConfig,无需转义,使用
${app:username}即可触发自定义Lookup插件的lookup方法,动态获取当前登录用户。
内容的提问来源于stack exchange,提问作者Felix Gaebler
相关产品推荐
相关产品推荐

