目录
1 日志路径带来的痛点
2 log4j.properties 文件的配置
3 彻底解决痛点
3.1 单独的 Java 程序包 (非 Java web 项目)
3.2 Web 项目
4 附录 - 获取当前项目, 类路径的几种方式
1 日志路径带来的痛点
Java 项目中少不了要和 log4j 等日志框架打交道, 开发环境和生产环境下日志文件的输出路径总是不一致, 设置为绝对路径的方式缺少了灵活性, 每次变更项目路径都要修改文件, 目前想到的最佳实现方式是: 根据项目位置自动加载并配置文件路径.
本文借鉴 Tomcat 的配置方式 "${catalina.home}/logs/catalina.out", 通过相对路径的方式设置日志的输出路径, 有其他解决方案的小伙伴, 请直接评论区交流哦
2 log4j.properties 文件的配置
- # 设置要输出的日志的级别 - 注意: properties 文件中的注释信息只能处于行首, 不要跟在行尾
- log4j.rootLogger=INFO,stdout,logfile
- ### 输出到控制台, Java 程序运行时的标准输出信息
- log4j.appender.stdout=org.apache.log4j.ConsoleAppender
- log4j.appender.stdout.Target=System.out
- log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
- # 2019-05-25 19:09:46
- log4j.appender.stdout.layout.ConversionPattern=%-d{
- yyyy-MM-dd HH:mm:ss
- } [%t] [%c] [%p] - %m%n
- ### 输出到日志文件
- # 按天滚动生成, 不支持 MaxFileSize, 而 RollingFileAppender 支持
- log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
- # 项目的 logs 目录下
- # log4j.appender.logfile.File=${
- base.dir
- }/logs/elastic-server.log
- log4j.appender.logfile.Append=true
- # 输出 INFO 及以上的日志, 按日期滚动就无须配置单个日志文件的最大体积了
- log4j.appender.logfile.Threshold=INFO
- # log4j.appender.logfile.MaxFileSize=100MB
- log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
- log4j.appender.logfile.layout.ConversionPattern=%-d{
- yyyy-MM-dd HH:mm:ss
- } [%t] [%c] [%p] - %m%n
3 彻底解决痛点
3.1 单独的 Java 程序包 (非 Java Web 项目)
单独的 Java 程序包, 需要通过命令 java -jar 或 java -cp 的方式启动;
我们可以在启动命令中加入系统运行时变量, 在 log4j 加载配置文件之前通过 System.getProperties("path")读取此变量, 即可实现灵活加载当前路径.
(1) 启动脚本设置:
假设当前项目的目录结构为:
/Projects/KafkaConsumer
丨 bin 项目的启动脚本
丨 conf 项目的配置文件
丨 lib 项目的其他依赖包
丨 bogs 项目的日志输出路径
启动脚本位于 bin 目录下, 内容示例如下:
- # 获取当前脚本的上级目录, 也就是 / Project/KafkaConsumer
- base_dir=$(dirname $(pwd))
- # 获取 Java 运行程序的位置, 并指定主类
- java_bin=$(which java)
- main_class="org.shoufeng.elastic.ConsumerMain"
- # 通过 - cp, 扩展 CLASSPATH, 指定主类的方式启动项目,
- # 并通过 "-D" 的方式向此程序的运行时环境中设置当前项目的路径,
- # 即可在程序中通过 System.getProperty("base.dir")获取此路径
- nohup ${
- java_bin
- } -Dbase.dir=${
- base_dir
- } -cp ${
- CLASSPATH
- }:${
- base_dir
- }/conf:${
- base_dir
- }/lib/* ${
- main_class
- }>> /dev/null &
(2) Java 程序读取变量:
实 log4j 的 FileAppender 本身支持动态设置文件路径, 如:
log4j.appender.logfile.File=${base.log}/logs/App.log
其中 "${base.log}" 是一个变量, 会被 System Property 中的 base.log 的值代替, 代码中的使用方式为:
- public static void main(String[] args) {
- // 获取系统运行时变量中的日志文件的输出路径
- // 此变量需要在启动命令中通过 - D 的方式设置
- String baseDir = System.getProperty("base.dir");
- if (baseDir == null) {
- // 开发环境中使用
- baseDir = System.getProperty("user.dir");
- System.setProperty("base.dir", baseDir);
- }
- log.info("==== 系统运行路径:" + System.getProperty("base.dir") + "====");
- // 其他处理逻辑......
- }
需要注意的是, 这种方式设置的环境变量只在当前 Java 进程 (也就是当前项目) 中有效, 并不会影响到其他项目.
3.2 Web 项目
如果是 Web 项目, 可通过修改 Web 容器的环境变量方式实现. 以 Tomcat 为例:
- # log4j 的配置文件支持服务器的 vm 环境变量, 格式类似 ${
- catalina.home
- }
- log4j.appender.R=org.apache.log4j.RollingFileAppender
- log4j.appender.R.File=${
- catalina.home
- }/logs/logs_tomcat.log
- log4j.appender.R.MaxFileSize=100MB
${catalina.home}是在 ${tomcat_home}/bin/catalina.sh 中通过 - D 参数设置的:
-Dcatalina.home="$CATALINA_HOME"
基于这个思路, 我们也可以向 Web 容器的 VM 参数中设置一个参数, 比如 - Dmylog.home="/Project/logs", 创建日志对象时即可使用.
4 附录 - 获取当前项目, 类路径的几种方式
- public static void main(String[] args) {
- // 获取 class 文件的绝对路径, 定位到具体的包名, 结果如:
- // /Projects/KafkaConsumer/target/classes/org/shoufeng/consumer/
- System.out.println(KafkaConsumer.class.getResource(""));
- // 获取 class 文件的绝对路径, 如: /Projects/KafkaConsumer/target/classes/,
- // 如果在 bin 目录下通过 java -jar 等命令启动时, 结果就是 /Projects/KafkaConsumer/bin/
- System.out.println(ClassLoader.getSystemResource(""));
- System.out.println(KafkaConsumer.class.getResource("/"));
- System.out.println(KafkaConsumer.class.getClassLoader().getResource(""));
- System.out.println(Thread.currentThread().getContextClassLoader().getResource(""));
- // 说明: 上述 4 种用法的返回结果类型都是 URL, 其 toString()返回的内容以 "file:" 开头, 可通过 ".toString().substring(5)" 去除
- // 获取工程的绝对路径, 如: /Projects/KafkaConsumer,
- // 若在 bin 中通过 java -jar 等命令启动, 路径就变成了: /Projects/KafkaConsumer/bin
- System.out.println(System.getProperty("user.dir"));
- }
参考资料
log4j 产生的日志位置设置 和 catalina.home,catalina.base
来源: https://www.cnblogs.com/shoufeng/p/11310086.html