Log4j,configurationWeb App使用相对path
我有一个Java Web应用程序,必须在Win或Linux机器上部署。 我现在想要添加log4j进行日志logging,我想为日志文件使用相对path,因为我不想在每个部署上更改文件path。 容器很可能是Tomcat,但不一定。
这样做的最好方法是什么?
Tomcat设置了一个catalina.home系统属性。 你可以在你的log4j属性文件中使用它。 像这样的东西:
log4j.rootCategory=DEBUG,errorfile log4j.appender.errorfile.File=${catalina.home}/logs/LogFilename.log
在Debian上(包括Ubuntu), ${catalina.home}
将不起作用,因为/ usr / share / tomcat6中没有链接到/ var / log / tomcat6。 这里只需使用${catalina.base}
。
如果你使用另一个容器,试着find一个类似的系统属性,或者定义你自己的。 设置系统属性将因平台和容器而异。 但是对于Linux / Unix上的Tomcat,我会在CATALINA_HOME / bin目录下创build一个setenv.sh文件。 它将包含:
export JAVA_OPTS="-Dcustom.logging.root=/var/log/webapps"
那么你的log4j.properties将是:
log4j.rootCategory=DEBUG,errorfile log4j.appender.errorfile.File=${custom.logging.root}/LogFilename.log
我终于这样做了。
添加了一个ServletContextListener,它执行以下操作:
public void contextInitialized(ServletContextEvent event) { ServletContext context = event.getServletContext(); System.setProperty("rootPath", context.getRealPath("/")); }
然后在log4j.properties文件中:
log4j.appender.file.File=${rootPath}WEB-INF/logs/MyLog.log
通过这样做,只要在设置“rootPath”系统属性之前不使用Log4j,Log4j就会写入正确的文件夹。 这意味着你不能使用它从ServletContextListener本身,但你应该能够在应用程序的任何其他地方使用它。
它应该在每个Web容器和操作系统上工作,因为它不依赖于特定于容器的系统属性,并且不受操作系统特定path问题的影响。 使用Tomcat和Orion Web容器进行testing,在Windows和Linux上运行良好。
你怎么看?
如果你使用Spring,你可以:
1)创build一个log4jconfiguration文件,例如“/WEB-INF/classes/log4j-myapp.properties”不要命名为“log4j.properties”
例:
log4j.rootLogger=ERROR, stdout, rollingFile log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender log4j.appender.rollingFile.File=${myWebapp-instance-root}/WEB-INF/logs/application.log log4j.appender.rollingFile.MaxFileSize=512KB log4j.appender.rollingFile.MaxBackupIndex=10 log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout log4j.appender.rollingFile.layout.ConversionPattern=%d %p [%c] - %m%n log4j.appender.rollingFile.Encoding=UTF-8
我们将在第(3)点后面定义“myWebapp-instance-root”
2)在web.xml中指定configuration位置:
<context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/classes/log4j-myapp.properties</param-value> </context-param>
3)为你的webapp的根目录指定一个唯一的variables名称,例如“myWebapp-instance-root”
<context-param> <param-name>webAppRootKey</param-name> <param-value>myWebapp-instance-root</param-value> </context-param>
4)添加一个Log4jConfigListener:
<listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener>
如果您select其他名称,请记住在log4j-myapp.properties中更改它。
看到我的文章(仅意大利语,但它应该是可以理解的): http : //www.megadix.it/content/configurare-path-relativi-log4j-utilizzando-spring
更新(2009/08/01)我把我的文章翻译成英文: http : //www.megadix.it/node/136
只是对伊克解决scheme的评论。
ServletContext
是你的问题的一个很好的解决scheme。 但是我不认为这对维护有好处。 大部分时间日志文件都需要长时间保存。
由于ServletContext
使文件在部署文件下,因此在重新部署服务器时将被删除。 我的build议是去rootPath的父文件夹,而不是孩子。
如果不在FileAppender的path属性中指定根目录,log4j是否只使用应用程序根目录? 所以你应该能够使用:
log4j.appender.file.File =日志/ MyLog.log
我已经完成了Java Web开发已经有一段时间了,但是这似乎是最直观的,也不会与写在$ {catalina.home} / logs目录中的其他不幸命名的日志相冲突。
如果你使用Maven我有一个很好的解决scheme给你:
-
编辑你的pom.xml文件以包含以下几行:
<profiles> <profile> <id>linux</id> <activation> <os> <family>unix</family> </os> </activation> <properties> <logDirectory>/var/log/tomcat6</logDirectory> </properties> </profile> <profile> <id>windows</id> <activation> <os> <family>windows</family> </os> </activation> <properties> <logDirectory>${catalina.home}/logs</logDirectory> </properties> </profile> </profiles>
在这里你定义了
logDirectory
属性专门给OS系列。 -
在
log4j.properties
文件中使用已定义的logDirectory
属性:log4j.appender.FILE=org.apache.log4j.RollingFileAppender log4j.appender.FILE.File=${logDirectory}/mylog.log log4j.appender.FILE.MaxFileSize=30MB log4j.appender.FILE.MaxBackupIndex=10 log4j.appender.FILE.layout=org.apache.log4j.PatternLayout log4j.appender.FILE.layout.ConversionPattern=%d{ISO8601} [%x] %-5p [%t] [%c{1}] %m%n
- 而已!
PS:我敢肯定,这可以使用Ant来实现,但不幸的是我没有足够的经验。
我的build议是,日志文件应该始终logging在Web应用程序的根上下文之上,所以如果我们重新部署webApp,我们不希望覆盖现有的日志文件。
作为对https://stackoverflow.com/a/218037/2279200的进一步评论; – 这可能会中断,如果Web应用程序隐式启动其他ServletContextListener(可能会早一些调用并且已经尝试使用log4j) – 在这种情况下,在确定日志根目录的属性被设置之前,log4jconfiguration将被读取和parsing。>日志文件将出现在当前目录(启动tomcat时的当前目录)的某个地方。
我只能想到以下解决scheme: – 将log4j.properties(或logj4.xml)文件重命名为log4j不会自动读取的文件。 – 在你的上下文filter中,在设置属性之后,调用DOM / PropertyConfigurator助手类来确保你的log4j – 。{xml,properties}被读取 – 重置log4jconfiguration(IIRC有一个方法来做到这一点)
这有点暴躁,但认为这是使水密的唯一途径。
我的解决scheme与Iker Jimenez的解决scheme类似,但使用System.setProperty(...)
我使用org.apache.log4j.PropertyConfigurator.configure(Properties)
。 为此,我还需要log4j无法自己find它的configuration,并手动加载(Wolfgang Liebich的回答中描述了这两点)。
这适用于Jetty和Tomcat,独立运行或者从IDE运行,需要零configuration,允许将每个应用程序的日志放在自己的文件夹中,而不pipe容器内有多less应用程序(这是基于System
的解决scheme的问题 )。 这样,你也可以把log4jconfiguration文件放在web应用程序的任何地方(例如,在一个项目中,我们已经在WEB-INF/
里面configuration了所有的文件)。
细节:
- 我有我的属性在类path
log4j-no-autoload.properties
文件(例如在我的Maven项目它最初在src/main/resources
,被打包到WEB-INF/classes
), -
它有文件appenderconfiguration为例如:
log4j.appender.MyAppFileAppender = org.apache.log4j.FileAppender log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log ...
-
而且我有这样的上下文监听器(用Java 7的“试用资源”语法获得更短的时间):
@WebListener public class ContextListener implements ServletContextListener { @Override public void contextInitialized(final ServletContextEvent event) { Properties props = new Properties(); InputStream strm = ContextListener.class.getClassLoader() .getResourceAsStream("log4j-no-autoload.properties"); try { props.load(strm); } catch (IOException propsLoadIOE) { throw new Error("can't load logging config file", propsLoadIOE); } finally { try { strm.close(); } catch (IOException configCloseIOE) { throw new Error("error closing logging config file", configCloseIOE); } } props.put("webAppRoot", event.getServletContext().getRealPath("/")); PropertyConfigurator.configure(props); // from now on, I can use LoggerFactory.getLogger(...) } ... }
您可以使用工作目录指定日志文件的相对path:
appender.file.fileName = ${sys:user.dir}/log/application.log
这与servlet容器无关,不需要将自定义variables传递给系统环境。