Java 为什么Log4J(jul)试图对来自供应商的字符串消息进行MessageFormat

Java 为什么Log4J(jul)试图对来自供应商的字符串消息进行MessageFormat,java,logging,lambda,log4j2,java.util.logging,Java,Logging,Lambda,Log4j2,Java.util.logging,使用Java1.8和log4j2.4jul适配器(Log4J-JUL-2.4.jar、Log4J-core-2.4.jar、Log4J-api-2.4.jar) 公共类SimpleTest{ 公共静态void main(字符串[]args)引发异常{ //动态写入配置文件 try(java.io.PrintStream p=new java.io.PrintStream(“./log4j jul test.xml”)){ p、 println(“”); p、 println(“”); p、 pr

使用Java1.8和log4j2.4jul适配器(Log4J-JUL-2.4.jar、Log4J-core-2.4.jar、Log4J-api-2.4.jar)

公共类SimpleTest{
公共静态void main(字符串[]args)引发异常{
//动态写入配置文件
try(java.io.PrintStream p=new java.io.PrintStream(“./log4j jul test.xml”)){
p、 println(“”);
p、 println(“”);
p、 println(“”);
p、 println(“”);
p、 println(“”);
p、 println(“”);
p、 println(“”);
p、 println(“”);
p、 println(“”);
p、 println(“”);
p、 println(“”);
p、 println(“”);
}
setProperty(“log4j.configurationFile”、“log4j jul test.xml”);
//指定java.util.logging.LogManager实现
//注释下面的行以查看标准JAVA记录器的反应
setProperty(“java.util.logging.manager”、“org.apache.logging.log4j.jul.LogManager”);
//获取普通Java记录器
java.util.logging.Logger Logger=java.util.logging.Logger.getLogger(“测试”);
//与标准和七月的伐木工人一起工作
logger.info(()->“将记录此第1行”);
//仅适用于标准Java logger。JUL正在尝试对其进行MessageFormat,但不应该这样做
info(()->“这第二行将{不}在七月之前被记录”);
//JUL将报告在处理Appender控制台时发生异常
//java.lang.IllegalArgumentException:无法分析参数编号:NOT
//位于java.text.MessageFormat.makeFormat(MessageFormat.java:1429)
//位于java.text.MessageFormat.applyPattern(MessageFormat.java:479)
//可与标准和JUL记录器一起使用
logger.log(java.util.logging.Level.INFO,“第三行将{0}被记录”,“成功”);
}
}
上面的代码非常简单,可以快速运行。试试看

有人知道为什么log4jjul试图对提供的字符串进行MessageFormat,而标准Java记录器显然不应该这样做吗?(现在已经有了传递任何参数的方法)

请注意,方法签名为:

java.util.logging.Logger.info(供应商)

java.util.logging.Logger的Javadoc说

大多数记录器输出方法采用“msg”参数。此msg参数可以是原始值或本地化键。格式化期间,如果记录器具有(或继承)本地化ResourceBundle,并且ResourceBundle具有msg字符串的映射,则msg字符串将替换为本地化值。否则将使用原始msg字符串。通常,格式化程序使用java.text.MessageFormat样式格式化参数,因此,例如,格式字符串“{0}{1}”将两个参数格式化为字符串


由于这个原因,Log4j预期为jul编写的代码会预期这一点,因此会将提供的字符串转换为。然而,在查看JDK提供的格式化程序时,似乎没有一个真正支持MessageFormat格式化。这值得在Log4j用户列表中讨论。

我认为在JUL案例中没有错误。它只是打印
INFO:JUL将{NOT}记录这第二行
。嗨,Sotirios,我在Log4J模式布局的code/config文件中添加了一个指示符,在日志条目“JUL:…”中添加了一个前缀,你能再试一次,看看输出是否有这个前缀吗?我在注释
setProperty
行时引用了这个指示符。默认记录器会记录它。您好,Sotirios,是的,Java标准实现确实显示了第2行,问题是当使用Log4J2 JUL LogManager时,不会输出同一行。感谢您的建议。我在Apache Log4J 2 JIRA中报告过这是一个bug,但是,在查看JDK提供的格式化程序时,它们似乎都不支持MessageFormat格式化。该方法提供了支持。JDK格式化程序扩展了该基类,因此所有使用formatMessage的格式化程序都支持MessageFormat格式化。
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");
  }
}