为什么 Log4J (jul) 试图 MessageFormat 来自 Supplier 的 String 消息
Why is Log4J (jul) attempting to MessageFormat a String message from Supplier
使用 Java 1.8 和 Log4J 2.4 JUL 适配器(log4j-jul-2.4.jar、log4j-core-2.4.jar、log4j-api -2.4.jar)
public class SimpleTest {
public static void main(String[] args) throws Exception {
// writing the configuration file on the fly
try (java.io.PrintStream p = new java.io.PrintStream("./log4j-jul-test.xml")) {
p.println("<Configuration>");
p.println(" <Appenders>");
p.println(" <Console name='Console' target='SYSTEM_OUT'>");
p.println(" <PatternLayout pattern='JUL: %d %t %-5level %m%n' />");
p.println(" </Console>");
p.println(" </Appenders>");
p.println(" <Loggers>");
p.println(" <Root level='debug'>");
p.println(" <AppenderRef ref='Console' />");
p.println(" </Root>");
p.println(" </Loggers>");
p.println("</Configuration>");
}
System.setProperty("log4j.configurationFile", "log4j-jul-test.xml");
// specifying the java.util.logging.LogManager implementation
// COMMENT THE LINE BELOW TO SEE HOW THE STANDARD JAVA LOGGER REACTS
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
// getting the plain Java logger
java.util.logging.Logger logger = java.util.logging.Logger.getLogger("test");
// works with both standard and JUL loggers
logger.info(() -> "This 1st line will be logged");
// works only with standard Java logger. JUL is attempting to MessageFormat it but shouldn't
logger.info(() -> "This 2nd line will {NOT} be logged by JUL");
// JUL will report that An exception occurred processing Appender Console
// java.lang.IllegalArgumentException: can't parse argument number: NOT
// at java.text.MessageFormat.makeFormat(MessageFormat.java:1429)
// at java.text.MessageFormat.applyPattern(MessageFormat.java:479)
// works with both standard and JUL logger
logger.log(java.util.logging.Level.INFO, "This 3rd line will {0} be logged", "successfully");
}
}
上面的代码很简单,可以运行很快。试试吧!
有谁知道为什么 Log4J JUL 试图 MessageFormat 提供的 String 显然不应该因为标准 Java 记录器没有? (现在无论如何都可以传递任何参数)
注意方法签名是:
java.util.logging.Logger.info(供应商<String>)
java.util.logging.Logger 的 Javadoc 说
Most of the logger output methods take a "msg" argument. This msg argument may be either a raw value or a localization key. During formatting, if the logger has (or inherits) a localization ResourceBundle and if the ResourceBundle has a mapping for the msg string, then the msg string is replaced by the localized value. Otherwise the original msg string is used. Typically, formatters use java.text.MessageFormat style formatting to format parameters, so for example a format string "{0} {1}" would format two parameters as strings.
正因为如此,Log4j 预计为 jul 编写的代码会预计到这一点,因此将提供的字符串转换为 MessageFormatMessage。但是,在查看 JDK 提供的格式化程序时,none 实际上似乎支持 MessageFormat 格式化。这值得在 Log4j 用户列表中讨论。
使用 Java 1.8 和 Log4J 2.4 JUL 适配器(log4j-jul-2.4.jar、log4j-core-2.4.jar、log4j-api -2.4.jar)
public class SimpleTest {
public static void main(String[] args) throws Exception {
// writing the configuration file on the fly
try (java.io.PrintStream p = new java.io.PrintStream("./log4j-jul-test.xml")) {
p.println("<Configuration>");
p.println(" <Appenders>");
p.println(" <Console name='Console' target='SYSTEM_OUT'>");
p.println(" <PatternLayout pattern='JUL: %d %t %-5level %m%n' />");
p.println(" </Console>");
p.println(" </Appenders>");
p.println(" <Loggers>");
p.println(" <Root level='debug'>");
p.println(" <AppenderRef ref='Console' />");
p.println(" </Root>");
p.println(" </Loggers>");
p.println("</Configuration>");
}
System.setProperty("log4j.configurationFile", "log4j-jul-test.xml");
// specifying the java.util.logging.LogManager implementation
// COMMENT THE LINE BELOW TO SEE HOW THE STANDARD JAVA LOGGER REACTS
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
// getting the plain Java logger
java.util.logging.Logger logger = java.util.logging.Logger.getLogger("test");
// works with both standard and JUL loggers
logger.info(() -> "This 1st line will be logged");
// works only with standard Java logger. JUL is attempting to MessageFormat it but shouldn't
logger.info(() -> "This 2nd line will {NOT} be logged by JUL");
// JUL will report that An exception occurred processing Appender Console
// java.lang.IllegalArgumentException: can't parse argument number: NOT
// at java.text.MessageFormat.makeFormat(MessageFormat.java:1429)
// at java.text.MessageFormat.applyPattern(MessageFormat.java:479)
// works with both standard and JUL logger
logger.log(java.util.logging.Level.INFO, "This 3rd line will {0} be logged", "successfully");
}
}
上面的代码很简单,可以运行很快。试试吧!
有谁知道为什么 Log4J JUL 试图 MessageFormat 提供的 String 显然不应该因为标准 Java 记录器没有? (现在无论如何都可以传递任何参数)
注意方法签名是:
java.util.logging.Logger.info(供应商<String>)
java.util.logging.Logger 的 Javadoc 说
Most of the logger output methods take a "msg" argument. This msg argument may be either a raw value or a localization key. During formatting, if the logger has (or inherits) a localization ResourceBundle and if the ResourceBundle has a mapping for the msg string, then the msg string is replaced by the localized value. Otherwise the original msg string is used. Typically, formatters use java.text.MessageFormat style formatting to format parameters, so for example a format string "{0} {1}" would format two parameters as strings.
正因为如此,Log4j 预计为 jul 编写的代码会预计到这一点,因此将提供的字符串转换为 MessageFormatMessage。但是,在查看 JDK 提供的格式化程序时,none 实际上似乎支持 MessageFormat 格式化。这值得在 Log4j 用户列表中讨论。