日志库选择
简而言之,在现代(比如2015年)的应用程序中,
记录日志推荐使用SLF4J API。
要让 FreeMarker 2.3.x. 使用SLF4J,在项目中加入依赖
org.slf4j:log4j-over-slf4j
即可,
要确保 log4j:log4j
不能存在。(从 FreeMarker 2.4.x 开始,尽管没有什么害处,
但也不再需要 log4j-over-slf4j
了。)
如果你对这些细节好奇,或者不能使用SLF4J,那么就继续阅读吧...
FreeMarker 整合了如下的日志包:SLF4J,Apache Commons Logging,Log4J 1.x,Avalon LogKit 和
java.util.logging
。默认情况下,
FreeMarker(在2.3.x版本下)会按如下顺序来查找日志包,
而且会自动使用第一个发现的包:
LOG4J(从2.3.22开始,如果正确安装了log4j-over-slf4j
,则会使用SLF4J来代替),
Apache Avalon LogKit, java.util.logging
。
正如你所见,Log4j有最高的优先级。org.apache.log4j.Logger
类会检测Log4j的存在,那么也就是说,像log4j-over-slf4j
或
log4j-1.2-api
,Log4j重定向也会有最高优先级。
在 FreeMarker 2.4 版本之前,因为向后兼容性的限制,
SLF4J和Apache Commons Logging不会被自动搜索。但是如果你正确安装了
org.slf4j:log4j-over-slf4j
(也就意味着,
在类路径下没有真实的Log4j,SLF4J有一个像 logback-classic
的支持实现),那么FreeMarker会直接使用SLF4J API来代替Log4j API
(从FreeMarker 2.3.22版本开始)。
请注意,应用Log4j2日志有个相似的技巧:如果
org.apache.logging.log4j:log4j-1.2-api
可用,
FreeMarker 2.3.x会使用它,因为它看起来就像Log4j,
但是所有的消息都会自动到Log4j2中。
如果自动检测没有给出你想要的结果,那么你可以设置系统属性
org.freemarker.loggerLibrary
来明确选择
(从2.3.22版本开始)一个日志库,比如:
java ... -Dorg.freemarker.loggerLibrary=SLF4J
系统属性支持的值有:
SLF4J
, CommonsLogging
,
JUL
(即 java.util.logging
),
Avalon
, auto
(默认行为),
none
(关闭日志)。
请注意,为了可靠的运行,系统属性应该在JVM启动时(向上面那样)就该设置好, 而不是在Java代码之后。
推荐使用SLF4J,因为它在 FreeMarker 中运行的更好, 也是因为从 FreeMarker 2.4 版本开始它有自动检测的最高优先级。
日志分类
由FreeMarker产生的所有日志信息会被记录到名称由
freemarker.
开头的日志记录器中。
现在被使用的记录器是:
日志分类名称 | 目标 |
---|---|
freemarker.beans |
记录Beans包装器模块的日志信息。 |
freemarker.cache |
记录模板加载和缓存相关的日志信息。 |
freemarker.runtime |
记录在模板执行期间的和特定分类无关的相关信息。 更重要的是,它会记录模板异常并在模板处理期间抛出 (但它却应该在现行的应用程序中禁用;稍后将会解释)。 |
freemarker.runtime.attempt |
记录在模板执行期间抛出的模板异常日志信息,
但是是开启DEBUG严重级别,并由
attempt /recover 指令捕捉。
请注意,该异常也会被记录到正常的日志记录器中
(比如freemarker.runtime )。 |
freemarker.servlet |
记录来自 FreemarkerServlet 类的消息。 |
freemarker.jsp |
记录FreeMarker JSP 支持的消息。 |
FreeMarker 会在模板执行期间使用
freemarker.runtime
记录异常,即便异常继续增加,最终由
Template.process
或 Environment.process
抛出。
(那些都是从应用程序或框架中调用模板时的API调用。)
良好的应用程序会记录它们抛出的异常,极少数情况下是处理它们而不去记录日志。
但是FreeMarker已经记录了异常,那么就会得到比期望的多一条日志记录。
要修复这个问题(从2.3.22版本开始),可以设置 log_template_exceptions
(Configurable.setLogTemplateExceptions(boolean)
)
为 false
。