当前位置: 首页 > 知识库问答 >
问题:

为Log4j 1.2注册自定义LoggerFactory的正确方法?

皇甫高阳
2023-03-14

我正在开发一个使用Log4j(1.2.16)日志记录的Web应用程序。为了避免编辑大量文件,我试图钩住自定义LoggerFactory实现,防止日志伪造。

似乎可以设置log4j。loggerFactory配置设置(project使用属性文件方法)指定要使用的记录器工厂。然而,这似乎不起作用。在检查了Log4j的源代码之后,似乎从未真正使用过该属性,即使它是由PropertyConfigurator类读取的。

检查更多的Log4j源代码,这似乎是实现我想要的唯一方法,我必须创建Log4j类的自定义子类。这是唯一的办法吗?

下面是我在web应用程序上下文侦听器中初始化Log4j时必须执行的操作,以便使用我的自定义记录器工厂:

package com.example.myapp.log4j;

import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.*;

public class MyLog4jInitContextListener implements ServletContextListener
{
  public void contextInitialized(
      ServletContextEvent event
  ) {
    this.context = event.getServletContext();

    String file = context.getInitParameter("log4jConfiguration");
    if (file != null) {
      String prefix = context.getRealPath("/");
      String pathname = prefix+file;
      event.getServletContext().log("Initializing log4j with "+pathname);
      org.apache.log4j.LogManager.setRepositorySelector(
          new org.apache.log4j.spi.DefaultRepositorySelector(
            new MyHierarchy(
              new org.apache.log4j.spi.RootLogger(
                (org.apache.log4j.Level)org.apache.log4j.Level.INFO))), this);
      new MyPropertyConfigurator().doConfigure(
          pathname, org.apache.log4j.LogManager.getLoggerRepository());
    } else {
      event.getServletContext().log(
          "No log4jConfiguration parameter specified");
    }
  }

  public void contextDestroyed(
      ServletContextEvent event
  ) {
    this.context = null;
  }

  private ServletContext context = null;
}

我不得不创建一个自定义的层次结构,因为它似乎对默认的日志工厂进行了硬编码。此版本确保在调用单参数getLogger()方法时使用my factory(这似乎是通过Logger.getLogger()实现的)-

我的等级制度。爪哇

package com.example.myapp.log4j;
import org.apache.log4j.Hierarchy;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggerFactory;

public class MyHierarchy extends Hierarchy
{
  public MyHierarchy(Logger root) { super(root); }
  @Override
  public Logger getLogger(String name) {
    return getLogger(name, defaultFactory);
  }
  private LoggerFactory defaultFactory = new MyLoggerFactory();
}

我不确定我需要自定义财产配置器,但我做了,以防有一些执行路径实际使用它保留引用的记录器工厂实例。

MyPropertyConfiguration。爪哇

package com.example.myapp.log4j;
import org.apache.log4j.PropertyConfigurator;

public class MyPropertyConfigurator extends PropertyConfigurator
{
  public MyPropertyConfigurator() {
    loggerFactory = new MyLoggerFactory();
  }
  @Override
  protected void configureLoggerFactory(java.util.Properties props) {
  }
}

以下是我的记录器工厂实现。MyEscapedLogger实现是Log4j的Logger类的一个子类,但在调用方法的超级版本之前,它会重写forcedLog()受保护的方法以转义消息中的字符。

我的博客工厂。爪哇

package com.example.myapp.log4j;
import org.apache.log4j.spi.LoggerFactory;

public class MyLoggerFactory implements LoggerFactory
{
  public Logger makeNewLoggerInstance(String name) {
    return new MyEscapedLogger(name);
  }
}

共有1个答案

许嘉珍
2023-03-14

在搜索了一段时间后,我发现了一个非常好的解决方案:

        final LoggerFactory loggerFactory = new LoggerFactory()
        {

            @Override
            public Logger makeNewLoggerInstance(String name)
            {
                return new MyCustomLogger(name);
                // or (if you don't need a custom Logger implementation):
                // Logger logger = new Logger(name);
                // logger.setSTUFF(...);
                // return logger;
            }

        };

        LoggerRepository rep = new Hierarchy(new RootLogger(Level.DEBUG))
        {

            @Override
            public Logger getLogger(String name)
            {
                return super.getLogger(name, loggerFactory);
            }

        };

        LogManager.setRepositorySelector(new DefaultRepositorySelector(rep), null);

我使用的是:log4j1.2.17

 类似资料:
  • 我是新来的Laravel。我有两种不同的用户类型:老师和学生。教师在网站注册表格中注册账户,但学生注册由windows应用程序提供。所以我必须为这个应用程序提供一个API。默认Laravel认证是足够的教师注册,但我可以使用相同的AuthController API注册?我不需要视图或重定向到网站。

  • 我已经为log4j2编写了一个自定义触发策略,该策略将被回滚。在每小时/天/你的工作时间间隔结束时,按照本SO帖子的建议记录文件。 虽然我遵循基于时间的触发策略约定(命名等),但我无法看到我的策略被实例化和使用。 解决方案由3个java文件和一个maven文件组成,可在github上获得 在这里,您可以从政策本身找到主要内容: log4j2。xml文件: 编辑: 在调试过程中,我了解到在log4j

  • 我试图弄清楚验证在Spring是如何工作的。到目前为止,我了解到有两种方法可以验证用户输入数据: JSR-303基于注释的验证。这种验证最适合于简单的对象字段验证。但是您也可以实现您的自定义类型级别注释,以便基于检查多个字段的值执行更复杂的验证。 Spring验证基于接口。似乎更适合更复杂的验证。 如果我想使用这两种方法,在controller中注册自定义验证器的正确方法是什么? 这就是我正在努力

  • 问题内容: 我已经将Spring Boot版本从2.0.3更新到2.1.1,但是我得到了: 我得到了错误-问题是在哪里看并不是一个好的指针。我已经看到了这个问题,但是我实际上更愿意继续禁止覆盖不明确的豆类。 有任何想法吗? 日志输出 问题答案: 好的,我自己发现了这个问题:我在项目中有两次: 和 所以我想说这是一个很好的Spring Boot新功能。 如果您看到这种错误,只需小心不要重复的注释。

  • Context.xml 堆栈跟踪:

  • 我想注册一个Avro模式,它在模式注册表上引用另一个Avro模式。 首先,我注册了以下基本Avro模式: 如果我尝试注册以下Avro架构,该架构引用“客户端”属性中的基本架构,则操作失败并出现错误422 这个问题似乎与指定自定义类型字段有关。 任何想法如何添加自定义类型,同时注册相关的模式在模式注册表?