Struts2 does not use Log4j, JCL (Apache Java Commons Logger) or slf4j directly.
It writes its own LoggerFactory (com.opensymphony.xwork2.util.logging.LoggerFactory), then lets it choose which LoggerFactory to use before logging.
For use in actions, it can be coded as follows:
private Logger logger = LoggerFactory.getLogger(FooAction.class);
String msg="debug level logger Info";
logger.debug(msg);
The log source code in struts2 involves:
In the init method of the org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter class, initialize the log object as follows:
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
Dispatcher dispatcher = null;
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
init.initLogging(config);
dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
postInit(dispatcher, filterConfig);
} finally {
if (dispatcher != null) {
dispatcher.cleanUpAfterInit();
}
init.cleanup();
}
}
The initLogging method in the org.apache.struts2.dispatcher.ng.InitOperations class,
public void initLogging( HostConfig filterConfig ) { String factoryName = filterConfig.getInitParameter("loggerFactory"); if (factoryName != null) { try { Class cls = ClassLoaderUtil.loadClass(factoryName, this.getClass()); LoggerFactory fac = (LoggerFactory) cls.newInstance(); LoggerFactory.setLoggerFactory(fac); } catch ( InstantiationException e ) { System.err.println("Unable to instantiate logger factory: " + factoryName + ", using default"); e.printStackTrace (); } catch ( IllegalAccessException e ) { System.err.println("Unable to access logger factory: " + factoryName + ", using default"); e.printStackTrace (); } catch ( ClassNotFoundException e ) { System.err.println("Unable to locate logger factory class: " + factoryName + ", using default"); e.printStackTrace (); } } }
The following code shows that Struts will load the LoggerFactory through a parameter named loggerFactory,
which can be set by setting
<filter>
<filter-name>strut2</filter-name>
<filter-class>
org.apache.struts2 in web.xml. dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
<init-param>
<param-name>loggerFactory</param-name>
<param-value>
com.opensymphony.xwork2.util.logging.commons.CommonsLoggerFactory
</ param-value>
</init-param>
</filter>
Let's take a look at the implementation of the LoggerFactory.getLogger(); method
See com.opensymphony.xwork2.util.logging.LoggerFactory class.
public static void setLoggerFactory(LoggerFactory factory) { lock.writeLock().lock(); try { LoggerFactory.factory = factory; } finally { lock.writeLock().unlock(); } }
Set the log processing class, where write lock processing is used.
public static Logger getLogger(String name) { return getLoggerFactory().getLoggerImpl(name); }
protected static LoggerFactory getLoggerFactory() { lock.readLock().lock(); try { if (factory != null) { return factory; } } finally { lock.readLock().unlock(); } lock.writeLock().lock(); try { if (factory == null) { String userLoggerFactory = System.getProperty(XWorkConstants.XWORK_LOGGER_FACTORY); if (userLoggerFactory != null) { try { Class clazz = Class.forName(userLoggerFactory); factory = (LoggerFactory) clazz.newInstance(); } catch (Exception e) { throw new XWorkException("System property [" + XWorkConstants.XWORK_LOGGER_FACTORY + "] was defined as [" + userLoggerFactory + "] but there is a problem to use that LoggerFactory!", e); } } else { try { Class.forName("org.apache.commons.logging.LogFactory"); factory = new com.opensymphony.xwork2.util.logging.commons.CommonsLoggerFactory(); } catch (ClassNotFoundException ex) { //commons-logging not found try slf4j LogFactory try { Class.forName("org.slf4j.LoggerFactory"); factory = new Slf4jLoggerFactory(); } catch (ClassNotFoundException cnfex) { // slf4j not found, falling back to jdk logging factory = new JdkLoggerFactory(); } } } } return factory; } finally { lock.writeLock().unlock(); } }
The log acquisition class has been fetched four times in total.
1. Read the configuration file of the webwork
2,org.apache.commons.logging.LogFactory
3,org.slf4j.LoggerFactory
4,JdkLoggerFactory