Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在slf4j中格式化异常?_Java_Logging_Slf4j_Slf4j Api - Fatal编程技术网

Java 如何在slf4j中格式化异常?

Java 如何在slf4j中格式化异常?,java,logging,slf4j,slf4j-api,Java,Logging,Slf4j,Slf4j Api,从我在网上找到的许多示例中,在slf4j中连接字符串的正确方法是使用内置的字符串格式 例如: LOGGER.error("ExceptionHandler throws {}" , appException); 我还尝试了无格式设置,结果相同: LOGGER.error("ExceptionHandler throws " , appException); 出于某种原因,这对我来说不起作用,我不知道我错过了什么。如果传递对象,是否使用不同的格式 上面的示例打印以下日志消息:

从我在网上找到的许多示例中,在slf4j中连接字符串的正确方法是使用内置的字符串格式

例如:

    LOGGER.error("ExceptionHandler throws {}" , appException);
我还尝试了无格式设置,结果相同:

    LOGGER.error("ExceptionHandler throws " , appException);
出于某种原因,这对我来说不起作用,我不知道我错过了什么。如果传递对象,是否使用不同的格式

上面的示例打印以下日志消息:

2018-07-18 02:38:19 ERROR c.a.c.c.p.ExceptionProcessor:67 - ExceptionHandler throws  {}
而不是使用常规连接时得到的预期消息:

LOGGER.error("ExceptionHandler throws " + appException);
或者当我手动调用.toString()时

根据Sonar的说法,最后一个选项是不正确的,因为:

因为printf样式的格式字符串是在运行时解释的,而不是 如果未经编译器验证,则它们可能包含导致错误的错误 正在创建错误的字符串。此规则静态验证 当 调用java.util.Formatter的format(…)方法, java.lang.String、java.io.PrintStream、MessageFormat和 PrintWriter类和的printf(…)方法 java.io.PrintStream或java.io.PrintWriter类

AppException类如下所示:

import java.io.Serializable;

import javax.ws.rs.core.Response.Status;


public class AppException extends Exception implements Serializable {

    private static final long serialVersionUID = 1L;

    private Error error;
    private Status status;

    public AppException(Error error, Status status) {
        this.error = error;
        this.status = status;
    }

    public AppException() {
    }

    public Error getError() {
        return error;
    }

    public void setError(Error error) {
        this.error = error;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "AppException [error=" + error + ", status=" + status + "]";
    }

}
我正在按照以下方式构建我的记录器:

private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionProcessor.class);

我使用的是
slf4japi 1.7.22

您相信的
LOGGER.error(“ExceptionHandler抛出{}”,appException)正在调用:

但它实际上是在呼吁:

因为这更适合参数类型

如果希望它调用第一个,请将参数强制转换为
对象

LOGGER.error("ExceptionHandler throws {}" , (Object) appException);
或者像您已经尝试过的那样调用
toString()

如果您使用了一个好的IDE来编写代码,IDE会帮助您解决这个问题。例如,在Eclipse中,如果将鼠标悬停在方法调用上,它将准确地显示正在调用的方法。当存在过载时非常有用



我刚刚重建了代码,并添加了两个日志条目:一个是调用toString,另一个是您建议的强制转换。有铸造的那个没有按预期工作,正在产生我最初发布的结果(没有消息)

无法复制。这里是MCVE(使用
org.slf4j:slf4j simple:1.7.25
):

输出

[main]错误测试-测试1:{}
java.lang.Exception:测试
at Test.main(Test.java:8)
[main]错误测试-测试2:java.lang.Exception:测试
第一次调用按原样打印消息(带有
{}
)和堆栈跟踪。
第二次呼叫打印消息,将
{}
替换为异常文本。

来自:

从SLF4J 1.6.0开始,在存在多个参数的情况下,如果日志语句中的最后一个参数是异常,则SLF4J将假定用户希望最后一个参数被视为异常,而不是简单参数

因此,编写(在SLF4J版本1.7.x和更高版本中)

将通过:

请考虑以下信息:

log.debug("Current count is " + count);
无论记录器是否记录消息,我们都要承担构建消息的成本。
Logback
提供了一种可选的参数化消息:

大括号{}将接受任何对象,并仅在验证日志消息是必需的之后,才使用其toString()方法生成消息。

:

另外,当异常作为最后一个参数传递给日志记录 方法,Logback将为我们打印堆栈跟踪


为什么要投反对票?你对方法调用的看法是正确的。在检查eclipse之后,它实际上调用了错误的方法。我应用了这个建议,但不幸的是它仍然给出了相同的结果result@Yeikel然后您没有编译代码,没有部署代码,或者您正在查看一个旧的日志条目。(我自己做过几次最后一个,所以现在我通常在重试之前删除日志文件,这样我就不会再犯那种错误)我只是重新生成代码,并添加了两个日志条目:一个是调用toString,另一个是您建议的强制转换。有铸造的那个并没有像预期的那样工作,并且产生了我最初发布的结果(没有消息)。一个完全错误的答案被提升。所描述的行为与SLF4J无关,可能是您对记录器实现感到困惑。实际上,在SLF4J 1.7.x中,记录器接口有方法签名:
public void error(字符串格式、对象…参数)这显然与最后一个异常是否可丢弃无关。这要由实际的记录器实现来处理。
Logger logger = LoggerFactory.getLogger("Test");
Exception e = new Exception("Test");
    
logger.error("Test 1: {}", e);           // calls error(String, Throwable)
logger.error("Test 2: {}", (Object) e);  // calls error(String, Object)
logger.error("one two three: {} {} {}", "a", "b", 
          "c", new Exception("something went wrong"));
log.debug("Current count is " + count);
log.debug("Current count is {}", count);
} catch (Exception e) {
    logger.error("Error dividing {} by {} ", 42, zero, e);
}