java 如何让 Jersey 使用 SLF4J 而不是 JUL?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4121722/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make Jersey to use SLF4J instead of JUL?
提问by yegor256
I've found a useful articlethat explains how to make Jersey to use SLF4J instead of JUL. Now my unit test looks like (and it works perfectly):
我找到了一篇有用的文章,解释了如何让 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 {
// ...
}
}
My pom.xml
includes these dependencies:
我的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>
It works perfectly, but I don't want to make the same configuration in every unit test. It's an obvious code duplication, which I would like to avoid. How can I do this more effectively?
它运行良好,但我不想在每个单元测试中都进行相同的配置。这是一个明显的代码重复,我想避免。我怎样才能更有效地做到这一点?
ps. Maybe it's not possible to optimize the code above and I'm doing the best I can?
附:也许无法优化上面的代码,而我正在尽我所能?
采纳答案by yegor256
The best way to do it is through a custom Listener. Being initialized before JSF servlet it should configure jul-to-slf4j bridge in contextInitialized(ServletContextEvent)
.
最好的方法是通过自定义Listener。在 JSF servlet 之前初始化它应该在contextInitialized(ServletContextEvent)
.
回答by assylias
If you are using the client API you can manually redirect the logs to slf4j (note that it may break in future versions although it seems unlikely):
如果您正在使用客户端 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); }
}
回答by L42
This worked for me:
这对我有用:
public abstract class JerseyTestSFL4J extends JerseyTest {
static {
// Get JerseyTest to use SLF4J instead of JUL
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
}
and then having my tests extend JerseyTestSFL4J
.
然后让我的测试扩展JerseyTestSFL4J
。
回答by Jure Skelin
Slf4jLogger
from org.apache.cxf:cxf-core
package is another option. It implements java.util.logging.Logger
and delegate cals to slf4J.
Slf4jLogger
从org.apache.cxf:cxf-core
包是另一种选择。它实现java.util.logging.Logger
cals 并将其委托给 slf4J。
Jersey server:
泽西服务器:
ResourceConfig config = new ResourceConfig(HelloWorldResource.class);
config.register(
new Slf4jLogger(this.getClass().getName(), null));
Jersey client:
泽西岛客户:
ClientBuilder
.newClient()
.register(
new LoggingFeature(
new Slf4jLogger(this.getClass().getName(), null)));
回答by Grigory Kislin
In my app Jersey logging (with proper pom.xml
and logback.xml
) works fine only with
在我的应用程序中, Jersey 日志记录(使用适当的pom.xml
和logback.xml
)仅适用于
SLF4JBridgeHandler.install();
For tests you can make base abstracttest with common configuration and extends other JUnit from it:
对于测试,您可以使用通用配置进行基本抽象测试,并从中扩展其他 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) {
...
回答by TJR
What it sounds like is you'd want the JUL/SLF4J configuration handle before JUnit starts testing so it could be covered for all tests? Here's a way you could do that.
听起来像是在 JUnit 开始测试之前您想要 JUL/SLF4J 配置句柄,以便它可以覆盖所有测试?这是您可以做到的一种方法。
Output
输出
MySuite.init()
MySuite()
getSuiteTests()
MyTest.init()
MyTest()
test()
Code
代码
@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});
}
}