How do I initialize Log4J in a web application?

醉面韋陀發表於2010-09-01

In other tutorials, we saw that log4j needs to be initialized in order to be used, and we saw how log4j can be initialized with a BasicConfigurator and initialized with a PropertyConfigurator. This typically occurs when an application starts up. In a web application, we'd also like log4j to start up when the application starts up. One straightforward way of doing this is to put this log4j initialization in a servletW, and specify for the servlet to start up when the application starts up.

Here is a web application project to illustrate this. It contains the log4j jarW file in its build path, a log4j.properties file, a web.xmlW file, a log4j initialization servlet, and a test servlet to try out our log4j initialization.

'log4j-webapp-demo' project

Let's start by examining our web.xml file. It contains references to our two servletsW, Log4JTestServlet and Log4JInitServlet. Log4JTestServlet gets mapped to /test so that it can be hit via a browser. The Log4JInitServlet starts up when the web application starts up because of the <load-on-startup> tag. Notice that it has an init-param and an init-value. This value gets passed to the servlet and specifies the location of our log4j.properties file.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="log4j-webapp-demo" version="2.4"
	xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<servlet>
		<servlet-name>Log4JTestServlet</servlet-name>
		<servlet-class>test.Log4JTestServlet</servlet-class>
	</servlet>
	<servlet>
		<servlet-name>Log4JInitServlet</servlet-name>
		<servlet-class>test.Log4JInitServlet</servlet-class>
		<init-param>
			<param-name>log4j-properties-location</param-name>
			<param-value>WEB-INF/log4j.properties</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Log4JTestServlet</servlet-name>
		<url-pattern>/test</url-pattern>
	</servlet-mapping>
</web-app>

Let's look at the Log4JInitServlet. In its init() method, it reads in the 'log4j-properties-location' init param value. If the init param doesn't exist, the application gets initialized via the BasicConfigurator. If is does exist, it gets the application's web directory location and appends the init param value to that. If the log4j.properties file exists at that location, it initializes log4j via the PropertyConfigurator using the log4j.properties file. If the log4j.properties file doesn't exist, the application gets initialized via the BasicConfigurator.

Log4JInitServlet.java

package test;

import java.io.File;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.PropertyConfigurator;

public class Log4JInitServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	public void init(ServletConfig config) throws ServletException {
		System.out.println("Log4JInitServlet is initializing log4j");
		String log4jLocation = config.getInitParameter("log4j-properties-location");

		ServletContext sc = config.getServletContext();

		if (log4jLocation == null) {
			System.err.println("*** No log4j-properties-location init param, so initializing log4j with BasicConfigurator");
			BasicConfigurator.configure();
		} else {
			String webAppPath = sc.getRealPath("/");
			String log4jProp = webAppPath + log4jLocation;
			File yoMamaYesThisSaysYoMama = new File(log4jProp);
			if (yoMamaYesThisSaysYoMama.exists()) {
				System.out.println("Initializing log4j with: " + log4jProp);
				PropertyConfigurator.configure(log4jProp);
			} else {
				System.err.println("*** " + log4jProp + " file not found, so initializing log4j with BasicConfigurator");
				BasicConfigurator.configure();
			}
		}
		super.init(config);
	}
}

Here is the log4j.properties file. I described properties files in another tutorial so I won't describe them here.

log4j.properties

# This sets the global logging level and specifies the appenders
log4j.rootLogger=INFO, myConsoleAppender

# settings for the console appender
log4j.appender.myConsoleAppender=org.apache.log4j.ConsoleAppender
log4j.appender.myConsoleAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.myConsoleAppender.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

Our test servlet is shown below. It contains a logger called log. Within its doGet() method, it displays the message 'Howdy' in response to a browser request, and it contains calls to log.debug(), log.info(), log.warn(), log.error(), and log.fatal().

Log4JTestServlet.java

package test;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

public class Log4JTestServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

	private static final long serialVersionUID = 1L;
	static Logger log = Logger.getLogger(Log4JTestServlet.class);

	public Log4JTestServlet() {
		super();
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("Howdy<br/>");
		log.debug("debug message");
		log.info("info message");
		log.warn("warn message");
		log.error("error message");
		log.fatal("fatal message");
	}

}

 

If we start up the project in EclipseSW with the TomcatSW bootstrap, we see the following console output:

Console Output

Mar 17, 2007 3:37:53 AM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
INFO: The Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\jdk1.5.0_09\jre\bin;.;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\QuickTime\QTSystem\;C:\jdk1.5.0_09\bin;C:\maven-2.0.4\bin;C:\jadnt158;C:\mysql-essential-5.0.27\bin
Mar 17, 2007 3:37:53 AM org.apache.coyote.http11.Http11BaseProtocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
Mar 17, 2007 3:37:53 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 906 ms
Mar 17, 2007 3:37:53 AM org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
Mar 17, 2007 3:37:54 AM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/5.5.20
Mar 17, 2007 3:37:54 AM org.apache.catalina.core.StandardHost start
INFO: XML validation disabled
Log4JInitServlet is initializing log4j
Initializing log4j with: C:\projects\workspace\log4j-webapp-demo\web\WEB-INF/log4j.properties
Mar 17, 2007 3:37:54 AM org.apache.catalina.core.ApplicationContext log
INFO: org.apache.webapp.balancer.BalancerFilter: init(): ruleChain: [org.apache.webapp.balancer.RuleChain: [org.apache.webapp.balancer.rules.URLStringMatchRule: Target string: News / Redirect URL: http://www.cnn.com], [org.apache.webapp.balancer.rules.RequestParameterRule: Target param name: paramName / Target param value: paramValue / Redirect URL: http://www.yahoo.com], [org.apache.webapp.balancer.rules.AcceptEverythingRule: Redirect URL: http://jakarta.apache.org]]
Mar 17, 2007 3:37:55 AM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
Mar 17, 2007 3:37:55 AM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
Mar 17, 2007 3:37:55 AM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
Mar 17, 2007 3:37:55 AM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
Mar 17, 2007 3:37:55 AM org.apache.coyote.http11.Http11BaseProtocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Mar 17, 2007 3:37:55 AM org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
Mar 17, 2007 3:37:56 AM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/94  config=null
Mar 17, 2007 3:37:56 AM org.apache.catalina.storeconfig.StoreLoader load
INFO: Find registry server-registry.xml at classpath resource
Mar 17, 2007 3:37:56 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 2375 ms

In the console output, notice that, among the Tomcat startup messages, our log4j gets initialized, as evidenced by the following lines taken from the above console output:

Log4JInitServlet is initializing log4j
Initializing log4j with: C:\projects\workspace\log4j-webapp-demo\web\WEB-INF/log4j.properties

If we hit our test servletW in a browser window, we see the 'Howdy' message as expected.

Hitting test servlet in browser window

If we now check our console window, we can see the logging messages that were output in the doGet() method of our test servlet. The output is formatted as we specified in the log4j.properties file. Notice that the log.debug() message in doGet() isn't displayed to the console, since our log4j.properties file specified that the log level is INFO.

Console output

Initializing log4j via a servlet that loads on web application start-up is a handy technique for initializing log4j.

相關文章