在简单的看了常用的Layout的使用方式后,我们来看看Layout的代码结构。因为Layout本身做的事情比Appender单纯很多,所以Layout的代码都是非常简洁的。我们先来看看Layout类:
public abstract class Layout implements OptionHandler {
abstract public String format(LoggingEvent event);
public String getContentType() {
return "text/plain";
}
public String getHeader() {
return null;
}
public String getFooter() {
return null;
}
abstract public boolean ignoresThrowable();
}
这个类本身是非常简单的。首先他实现了OptionHandler接口,所以同样Layout也允许参数的设置,比如我们使用PatternLayout,就会配置conversionPattern,其实就是PatternLyaout里面对应的属性名称。
接下来是contentType,返回的是该layout返回内容的MIME格式。一般情况下,输出的都是普通的字符串,所以返回的都是text/plain,而我们刚才看到的HTMLLayout,返回的就应该是text/html。
getHeader和getFooter方法,是可以在输出真正日志内容之前或之后输出一些特定的内容。非常典型的使用就是在HTMLLayout中,在输出真正的日志内容之前,首先得输出<html><body><table>这些东西,这个方法是在配置Appender的时候就输出了。而getFooter,就是输出最后的内容,比如</body></html>这些,这个方法是在appender.close方法中调用的。
剩下两个就是每个Layout需要去实现的,一个是format,就是真正怎么去执行LoggingEvent转换成String的逻辑了;一个是ignoresThrowable(),这个方法返回一个boolean值,意思很简单,如果layout自己要负责LoggingEvent中包含的错误(比如log.error(throwable))信息的处理,就返回false,如果layout不能处理这些错误,则返回true,让错误的处理交给appender去处理。
每个方法都是非常简单的,下面来随便看看SimpleLayout的代码,大概理解下定义Layout的方式:
public class SimpleLayout extends Layout {
StringBuffer sbuf = new StringBuffer(128);
public SimpleLayout() {
}
public void activateOptions() {
}
public String format(LoggingEvent event) {
sbuf.setLength(0);
sbuf.append(event.getLevel().toString());
sbuf.append(" - ");
sbuf.append(event.getRenderedMessage());
sbuf.append(LINE_SEP);
return sbuf.toString();
}
public boolean ignoresThrowable() {
return true;
}
}
整个代码非常简单,仅仅是在format方法中,去输出event.getLevel(即日志的日志级别)和event.getRenderedMessage()即输出的日志内容。这里简单注意一下,event有两个得到日志内容的方法,一个是event.getRenderedMessage(),一个是event.getMessage();请注意这两个方法的不同,getMessage会直接输出日志的内容,这个内容有可能是一个Object类的任何子类,而getRenderedMessage()输出的是使用ObjectRenderer合成之后的最终的String,关于ObjectRenderer有专门的介绍。
public abstract class Layout implements OptionHandler {
abstract public String format(LoggingEvent event);
public String getContentType() {
return "text/plain";
}
public String getHeader() {
return null;
}
public String getFooter() {
return null;
}
abstract public boolean ignoresThrowable();
}
这个类本身是非常简单的。首先他实现了OptionHandler接口,所以同样Layout也允许参数的设置,比如我们使用PatternLayout,就会配置conversionPattern,其实就是PatternLyaout里面对应的属性名称。
接下来是contentType,返回的是该layout返回内容的MIME格式。一般情况下,输出的都是普通的字符串,所以返回的都是text/plain,而我们刚才看到的HTMLLayout,返回的就应该是text/html。
getHeader和getFooter方法,是可以在输出真正日志内容之前或之后输出一些特定的内容。非常典型的使用就是在HTMLLayout中,在输出真正的日志内容之前,首先得输出<html><body><table>这些东西,这个方法是在配置Appender的时候就输出了。而getFooter,就是输出最后的内容,比如</body></html>这些,这个方法是在appender.close方法中调用的。
剩下两个就是每个Layout需要去实现的,一个是format,就是真正怎么去执行LoggingEvent转换成String的逻辑了;一个是ignoresThrowable(),这个方法返回一个boolean值,意思很简单,如果layout自己要负责LoggingEvent中包含的错误(比如log.error(throwable))信息的处理,就返回false,如果layout不能处理这些错误,则返回true,让错误的处理交给appender去处理。
每个方法都是非常简单的,下面来随便看看SimpleLayout的代码,大概理解下定义Layout的方式:
public class SimpleLayout extends Layout {
StringBuffer sbuf = new StringBuffer(128);
public SimpleLayout() {
}
public void activateOptions() {
}
public String format(LoggingEvent event) {
sbuf.setLength(0);
sbuf.append(event.getLevel().toString());
sbuf.append(" - ");
sbuf.append(event.getRenderedMessage());
sbuf.append(LINE_SEP);
return sbuf.toString();
}
public boolean ignoresThrowable() {
return true;
}
}
整个代码非常简单,仅仅是在format方法中,去输出event.getLevel(即日志的日志级别)和event.getRenderedMessage()即输出的日志内容。这里简单注意一下,event有两个得到日志内容的方法,一个是event.getRenderedMessage(),一个是event.getMessage();请注意这两个方法的不同,getMessage会直接输出日志的内容,这个内容有可能是一个Object类的任何子类,而getRenderedMessage()输出的是使用ObjectRenderer合成之后的最终的String,关于ObjectRenderer有专门的介绍。