怎样在log4j.xml配置文件中引入变量:小公司经验较多的我和阿里UC等大公司经验较多的Boss,一些技术交流和探讨

从最初学习使用log4j的时候,网上和书本上主要都是使用“log4j.properties”这种属性格式,配置日志。多年以来,一直使用这种格式,总的来说,简单、够用。
 
   而有十多年经验的Boss,不建议使用properties格式配置,而是用xml格式配置。Boss之前在阿里(支付宝、淘宝)、UC等大公司工作过。

我们有个很明显的不同:  我比较注重,简单、快速。Boss比较注重,规范、严谨。

我的观点:没有对与错,只有适用与不适用。每个人都是根据自己的经历和追求,做出的技术选择。对于技术使用者来讲,明白不同配置的好处和坏处,才是需要注意的。

就log4j.xml这种配置来说,功能确实可能更多一些,可以单独把 业务日志和普通的系统日志分离,运维过程中,很容易看到业务错误,从而更快的解决问题。
 ------------------------------------------------------------------------------------------------------------
     另外,Boss觉得需要把log4j的输出目录配置成变量。比如:<param name="File" value="${log4jOutputPath}/front/default.log" />,log4jOutputPath可以是“C:/log4j/”。

Boss根据之前在阿里的工作经验,开发和运维可能完全是2拨人。开发只管写代码,把代码写好,没有功能和业务问题。运维,负责把代码部署好,域名解析、Nginx、Tomcat、日志配置。运维导致的问题,运维背锅。功能问题,开发背锅。职责分明,流水化作业。
    我对这种流水化的作业是非常认同的,这样的企业生产效率才高,才能为国家和社会创造更多的价值。

而象武汉一起好等很多在技术方面,偏向中小型规模的企业来说,开发和运维很可能就是“同一拨人”。这个时候,系统配置要怎么做,就是个值得探讨的问题了。
 ------------------------------------------------------------------------------------------------------------
   Boss最初建议,修改Tomcat的启动脚本,在里面增加变量配置,比如“-Dlog4jOutputPath=c:/log4j”。

我一听,就不太赞成这种做法了。对于开发与运维都是一拨人,经常需要和其它开发人员交流的情况,修改Tomcat自身的配置比较麻烦。
为什么这么说呢?

Tomcat是系统级的程序,而我们的代码是应用级的程序。开发者,对自己的应用程序,一般是掌控度非常高的,但是对于Tomcat等不是自己写的系统程序,把控度比较低。Tomcat的随便一行启动代码,不小心改错了,就启动不了了。
   修改Tomcat还有坏处,本地开发、线上部署、交接给其它客户,还得让客户去修改Tomcat这个和咱们的程序无关的配置,是不科学的。

我的建议是,把这些配置,放在外围,写入个文件,比如startupTomcat.sh,在启动的时候指定参数。每个人都可以很灵活地修改log4j等配置参数。
   初步商议,我们采用这种做法。
 
   总结下:

<appender name="DEFAULT-APPENDER" class="org.apache.log4j.DailyRollingFileAppender">
		<param name="File" value="${log4jOutputPath}/front/default.log" /><!-- 设置日志输出文件名 -->
</appender>

启动的时候,增加VM参数,-Dlog4jOutputPath=c:/log4j

----------------------------------------------------------------------------------------------------------
第2种做法,适合开发和运维都是同一人的情况,把log4j的变量,放在Web.xml里,部署的时候,需要手动修改这个变量。

log4j配置

可在web.xml中配置log4j.xml的位置,参数名称为:log4jXmlPath。

也可以,配置log4j的日志输出位置的目录,参数名称为:log4jOutputPath。

<servlet>
     <servlet-name>Log4jInit</servlet-name>
     <servlet-class>cn.fansunion.common.web.Log4jInit</servlet-class>
     <init-param> <param-name>log4jXmlPath</param-name> <param-value>C:/log4j.xml</param-value> </init-param>
      <init-param> <param-name>log4jOutputPath</param-name> <param-value>C:/log4j/xiaolei2</param-value> </init-param>
    <load-on-startup>0</load-on-startup>
</servlet> 

注意:这2个参数都必须输入绝对地址,如果log4jXmlPath没有值,或者对应的文件不存在,将把classpath下的log4j.xml作为默认配置文件。如果再找不到,将报错,log4j配置失败。

如果log4jOutputPath没有值,或者对应的文件不存在,将把classpath下的log4j文件夹作为默认的输出目录。

Author:
[email protected] 2015年1月8日

Java代码 Log4jInit.java

public class Log4jInit extends HttpServlet {

	private static final long serialVersionUID = 1L;

	public void init(ServletConfig config) throws ServletException {

		// 从web.xml中找到log4j的输出目录
		String log4jOutputPath = config.getInitParameter("log4jOutputPath");
		// 默认的日志输出位置
		if (StringUtils.isBlank(log4jOutputPath)) {
			log4jOutputPath = Log4jInit.class.getClassLoader().getResource("")
					.getFile()
					+ "/log4j";
		}
		File log4jOutputPathFile = new File(log4jOutputPath);
		// 如果输出文件不存在,手动创建
		boolean log4xmlFileExists = log4jOutputPathFile.exists();
		if (!log4xmlFileExists) {
			System.out.println(log4jOutputPathFile.mkdirs());
		}
		// log4j.xml文件中的变量是在这里设置的
		System.setProperty("log4jOutputPath", log4jOutputPath);

		// 从web.xml中找到log4j.xml的输出目录
		String log4jXmlPath = config.getInitParameter("log4jXmlPath");
		boolean exist = false;
		// 如果在web.xml手动配置,log4jXmlPath应该使用绝对地址,否则,就使用默认的位置和文件名就行
		if (StringUtils.isNotBlank(log4jXmlPath)) {
			File file = new File(log4jXmlPath);
			exist = file.exists();
		}
		// log4jXmlPath默认位于classpath下log4j.xml
		if (!exist) {
			URL resource = Log4jInit.class.getClassLoader().getResource(
					"log4j.xml");
			if (resource != null) {
				log4jXmlPath = resource.getFile();
			}
		}
		DOMConfigurator.configure(log4jXmlPath);
	}
}

----------------------------------------------------------------------------------------------------------
  从技术方面的学习,加入一起好,遇到Boss,是我人生的大幸。要不然,我很难这么快就了解阿里等大公司的一些实际做法。
  我决定扎根武汉,是不太可能去阿里系工作的。

怀揣梦想的我,也不可能委身于阿里。

小雷FansUnion-博学的互联网技术工作者,全栈式多屏开发工程师

2015年1月25日

湖北-武汉-循礼门

时间: 2024-10-07 12:38:32

怎样在log4j.xml配置文件中引入变量:小公司经验较多的我和阿里UC等大公司经验较多的Boss,一些技术交流和探讨的相关文章

XML配置中 引入外部property文件

新建properties配置文件 内容如下: jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc\:mysql\://localhost\:3306/book_mybatis?user\=root&password\=root&useUnicode\=true&characterEncoding\=UTF-8 有两个属性, ①jdbc.dirverClassName ; ②jdbc.url. <!-- 导入属性配置

如何在web.xml文件中引入其他的xml文件

最近在做一个Servlet+javaBean的项目,服务器用的是tomcat.因此,所有的页面都是servlet请求,而且很多,需要在web.xml文件中进行配置.导致web.xml文件特别大,而且这个系统以后会做大,并且会出现系统拆分,为了便于以后拆分,于是想到将web.xml文件中的servlet和servlet-mapping能够从web.xml脱离出来,用其他xml文件保存然后在web.xml文件中引入这些文件,就想类似引入struts.config一样.        在网上找了半天也

@Required 注释应用于 bean 属性的 setter 方法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常。

@Required 注释应用于 bean 属性的 setter 方法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常. java public class Student { private Integer age; private String name; @Required public void setAge(Integer age) { this.age = age; } public

数据层spring-dao.xml配置文件中C3P0连接池配置详解

数据层spring-dao.xml配置文件中C3P0连接池配置详解 先放上两种配置文件bean的相关代码,文章下面会有详细的配置属性的讲解,大家可以自己添加配置和修改配置普通单一数据库连接池配置: <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 配置连接池属性 --> <property name="driverClas

Spring中Bean的作用域、Spring的自动注入、在spring配置文件中引入属性文件

1. Bean的作用域 Bean的作用域默认为单例模式. 2. 自动注入 3. 在spring配置文件中引入属性文件 Bean的作用域默认为单例模式. 原文地址:https://www.cnblogs.com/mcl2238973568/p/11478426.html

log4j.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <!-- 根节点的配置顺序: renderer appender pl

获取web.xml配置文件中的初始化值

TestServletConfig.java package com.huawei.config; import java.io.IOException;import java.util.Enumeration; import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpSe

sping配置文件中引入properties文件方式

<!-- 用于引入 jdbc有配置文件参数 可以使用PropertyPlaceholderConfigurer 或者PropertyOverrideConfigurer --> <bean class="org.springframework.beans.factory.PropertyPlaceholderConfigurer"> <property name="location"> <value>classpath

selenium元素中引入变量的方法

# encoding:utf-8 from selenium import webdriver import time driver = webdriver.Firefox() driver.get("http://www.baidu.com") # 下面这一段使用的是python中变量的方法,简单吧! class Deleteproperty: def deleteproperty(self,rj,num=10,frequency=1): num=str(num) for i in