如何让泽西使用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 extends AbstractTestSuite>) 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.xml
和logback.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)));