V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Weixiao0725
V2EX  ›  Java

Java 中如何实现同一个应用中多日志"实例"输出

  •  
  •   Weixiao0725 · 2016-10-23 23:32:30 +08:00 · 3296 次点击
    这是一个创建于 2981 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 Java 中如何实现像 tomcat 中的那样,多个 web 项目都可以有自己的日志输出。我模拟了一下,大致的过程是:主 main 函数中配置一个日志实例(log4j ),然后启动多个线程,每个线程中重新生成一个 ClassLoader ,然后扫描一个目录下的所有 jar 包和配置文件,然后反射执行其中的某个方法(这个方法会打印日志 logger.info("blabla..."))。

    但是实验的结果总是,所有的日志都写到了 main 函数中配置的日志实例。我刚开始以为是线程的 contextClassLoader 没有设置,后来在线程中 Thread.currentThread().setContextClassLoader(cl);发现还是不行,被这个问题卡住好久了,网上资料也是各种看,一直没有实现。蓝瘦,香菇。。。

    如果您了解的话,一定给我留言,提一下建议和思路也是好的,感谢!

    3 条回复    2016-10-24 01:35:17 +08:00
    Weixiao0725
        1
    Weixiao0725  
    OP
       2016-10-23 23:38:24 +08:00
    关于 tomcat 的实现,我也研究了几天, tomcat 的做法是自己实现了一个 ClassLoaderLogManager ,然后启动的时候设置了这个系统属性-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager ,意思好像是通过这个全局统一的日志管理类来根据不同的 ClassLoader 管理日志实例。但是我修改了这部分源代码重新打包到 tomcat 目录下替换了原来的实现类(${tomcat}/bin/tomcat-juli.jar),发现其实当一个 web 项目中比如引入了 log4j 后,其日志的生成并没有与 ClassLoaderLogManager 发生任何关系。而且我发现 log4j 本身也有自己的 LogManager 实现。所以不清楚 tomcat 是如何把各个日志实例区分开的。
    SoloCompany
        2
    SoloCompany  
       2016-10-24 00:49:08 +08:00
    这问题很简单,和 tomcat 自己的 logger 实现 (juli) 无关
    你把 log4j 的实现放到 tomcat/lib 目录的话,一样有同样的问题
    同样的,如果你想自己实现容器,首先要保证你的实例互相是隔离的(没有直接的互相引用关系),然后必须确保每个实例所引用到的 log4j 是不同的(就是必须是应用自己的 classloader 加载的实现,而不是 delegate 给 parent 所加载的实现)
    Weixiao0725
        3
    Weixiao0725  
    OP
       2016-10-24 01:35:17 +08:00
    我以为的隔离只是用不同的 classloader 实例加载相关的 jar ,我也确实是这么做的。但是我不知道为什么似乎我开启了两个线程实验的时候(两个线程中先是生成自己的定制的 classloader ,然后将相关的文件和 jar 包扫描进来,然后调用其中某个类的实例的方法,这个方法会打印一条日志),但是不同 classloader 加载的相关实现都将日志输出到同一个文件中了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2792 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 689ms · UTC 11:41 · PVG 19:41 · LAX 03:41 · JFK 06:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.