【问题标题】:How to make Jersey to use SLF4J instead of JUL?如何让 Jersey 使用 SLF4J 而不是 JUL?
【发布时间】:2011-05-06 12:33:10
【问题描述】:

我发现 a useful article 解释了如何让 Jersey 使用 SLF4J 而不是 JUL。现在我的单元测试看起来像(并且效果很好):

public class FooTest extends JerseyTest {
  @BeforeClass
  public static void initLogger() {
    java.util.logging.Logger rootLogger =
      java.util.logging.LogManager.getLogManager().getLogger("");
    java.util.logging.Handler[] handlers = rootLogger.getHandlers();
    for (int i = 0; i < handlers.length; i++) {
      rootLogger.removeHandler(handlers[i]);
    }
    org.slf4j.bridge.SLF4JBridgeHandler.install();
  }
  public FooTest() {
    super("com.XXX");
  }
  @Test
  public void testSomething() throws Exception {
    // ...
  }
}

我的pom.xml 包含这些依赖项:

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.6.1</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.6.1</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>jul-to-slf4j</artifactId>
  <version>1.6.1</version>
</dependency>
<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.2.16</version>
</dependency>

它运行良好,但我不想在每个单元测试中都进行相同的配置。这是一个明显的代码重复,我想避免。我怎样才能更有效地做到这一点?

ps。可能无法优化上面的代码,我已经尽力了?

【问题讨论】:

  • 只是对 initLogger() 的增强,你可以使用这个:SLF4JBridgeHandler.removeHandlersForRootLogger(); java.util.logging.LogManager.getLogManager().reset(); SLF4JBridgeHandler.install();

标签: java logging log4j jersey slf4j


【解决方案1】:

如果您使用客户端 API,您可以手动将日志重定向到 slf4j(请注意,它可能会在未来的版本中中断,尽管这似乎不太可能):

Logger LOG = LoggerFactory.getLogger(MyClass.class); //slf4j logger

WebTarget ws = ClientBuilder.newClient(config)
                  .register(new LoggingFilter(new JulFacade(), true));

private static class JulFacade extends java.util.logging.Logger {
  JulFacade() { super("Jersey", null); }
  @Override public void info(String msg) { LOG.info(msg); }
}

【讨论】:

    【解决方案2】:

    最好的方法是通过自定义Listener。在 JSF servlet 之前初始化它应该在 contextInitialized(ServletContextEvent) 中配置 jul-to-slf4j 桥。

    【讨论】:

    • 仅供参考,jul-to-slf4j 桥在性能方面可能代价高昂。 slf4j.org/legacy.html#jul-to-slf4j
    • 这些人projects.lidalia.org.uk/sysout-over-slf4j/quickstart.html 提供了一个 jar,通过使用他们的 jar 将您的 stdout 和 stderr 重定向到 sl4j,向您的 web.xml 添加一个类侦听器,并添加另一行代码。我试过了,但没有正确配置它。 (没有进一步研究。)无论如何,这可能对某人有帮助。
    【解决方案3】:

    这对我有用:

    public abstract class JerseyTestSFL4J extends JerseyTest {
    
      static {
        // Get JerseyTest to use SLF4J instead of JUL
        SLF4JBridgeHandler.removeHandlersForRootLogger();
        SLF4JBridgeHandler.install();
      }
    }
    

    然后让我的测试扩展 JerseyTestSFL4J

    【讨论】:

      【解决方案4】:

      听起来你想要在 JUnit 开始测试之前使用 JUL/SLF4J 配置句柄,以便可以覆盖所有测试?这是您可以做到的一种方法。

      输出

      MySuite.init()
      MySuite()
      getSuiteTests()
      MyTest.init()
      MyTest()
      test()
      

      代码

      @RunWith(AbstractTestSuite.TestSuiteRunner.class)
      public abstract class AbstractTestSuite {
         public static class TestSuiteRunner extends Suite {
            public TestSuiteRunner(Class<?> klass) throws Exception {
               super(klass, ((Class<? extends AbstractTestSuite>) klass).newInstance().getSuiteClasses());
            }
         }
      
         public Class<?>[] getSuiteClasses() {
            List<Class<?>> all = new ArrayList<Class<?>>();
            for (Class<?> testClass : getSuiteTests()) {
               all.add(testClass);
            }
            return all.toArray(new Class<?>[0]);
         }
      
         protected abstract Iterable<Class<?>> getSuiteTests();
      }
      
      public class MySuite extends AbstractTestSuite {
         public static class MyTest {
            static {
               System.out.println("MyTest.init()");
            }
      
            public MyTest() {
               System.out.println("MyTest()");
            }
      
            @Test
            public void test() {
               System.out.println("test()");
               assertTrue(true);
            }
         }
      
         static {
            System.out.println("MySuite.init()");
         }
      
         public MySuite() {
            System.out.println("MySuite()");
         }
      
         @Override
         protected Iterable<Class<?>> getSuiteTests() {
            System.out.println("getSuiteTests()");
            return Arrays.asList(new Class<?>[] {MyTest.class});
         }
      }
      

      【讨论】:

      • @TJ 我可以不使用 Java 代码,只使用配置XML/.properties 文件吗?
      【解决方案5】:

      在我的应用程序 Jersey 日志记录(使用正确的 pom.xmllogback.xml)仅适用于

          SLF4JBridgeHandler.install(); 
      

      对于测试,您可以使用通用配置进行基本 abstract 测试并从中扩展其他 JUnit:

      public abstract class AbstractTest {
      
          private static final Logger LOG = LoggerFactory.getLogger(AbstractTest.class);
      
          static {
              SLF4JBridgeHandler.install();
          }
      
          @Rule
          public ExpectedException thrown = ExpectedException.none();
      
          @Rule
          // http://stackoverflow.com/questions/14892125/what-is-the-best-practice-to-determine-the-execution-time-of-the-bussiness-relev
          public Stopwatch stopwatch = new Stopwatch() {
              @Override
              protected void finished(long nanos, Description description) {
                 ...
      

      【讨论】:

        【解决方案6】:

        Slf4jLogger 来自org.apache.cxf:cxf-core 包是另一种选择。它实现了 java.util.logging.Logger 并将 cals 委托给 slf4J。

        泽西服务器:

        ResourceConfig config = new ResourceConfig(HelloWorldResource.class);
        config.register(
            new Slf4jLogger(this.getClass().getName(), null));
        

        泽西岛客户:

        ClientBuilder
            .newClient()
            .register(
                new LoggingFeature(
                        new Slf4jLogger(this.getClass().getName(), null)));
        

        【讨论】:

          猜你喜欢
          • 2014-12-31
          • 1970-01-01
          • 1970-01-01
          • 2011-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-08
          相关资源
          最近更新 更多