如何让泽西使用SLF4J代替JUL?

我找到了一篇有用的文章 ,解释了如何让泽西使用SLF4J而不是JUL。 现在我的unit testing看起来像(并且它完美地工作):

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包含以下依赖项:

  org.slf4j slf4j-api 1.6.1   org.slf4j slf4j-log4j12 1.6.1   org.slf4j jul-to-slf4j 1.6.1   log4j log4j 1.2.16  

它工作得很好,但我不想在每个unit testing中进行相同的配置。 这是一个明显的代码重复,我想避免。 我怎样才能更有效地做到这一点?

PS。 也许不可能优化上面的代码,我尽我所能?

如果您使用的是客户端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); } } 

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

听起来是在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) klass).newInstance().getSuiteClasses()); } } public Class[] getSuiteClasses() { List> all = new ArrayList>(); for (Class testClass : getSuiteTests()) { all.add(testClass); } return all.toArray(new Class[0]); } protected abstract Iterable> 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> getSuiteTests() { System.out.println("getSuiteTests()"); return Arrays.asList(new Class[] {MyTest.class}); } } 

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

  SLF4JBridgeHandler.install(); 

对于测试,您可以使用通用配置进行基本抽象测试,并从中扩展其他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) { ... 

这对我有用:

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

然后让我的测试扩展JerseyTestSFL4J

来自org.apache.cxf:cxf-core 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)));