Tomcat在日志JAR包共享情况下按webapp打印日志方案

举报
eagle 发表于 2019/01/25 18:01:45 2019/01/25
【摘要】 Tomcat的多webapp要分日志打印的话,简单方案是把日志JAR包各放各webapp的lib目录,分别使用。但是这样的话,日志JAR包加载多份,资源有所浪费。最好是日志JAR包共用,用其它的隔离机制实现。万幸,log4j提供了一个叫LoggerRepository的API,可以做这个事情。实现类图:本例以使用slf4j打印为例说明。其中org.apache.log4j.Logger和or...

Tomcat的多webapp要分日志打印的话,简单方案是把日志JAR包各放各webapp的lib目录,分别使用。但是这样的话,日志JAR包加载多份,资源有所浪费。

最好是日志JAR包共用,用其它的隔离机制实现。

万幸,log4j提供了一个叫LoggerRepository的API,可以做这个事情。


实现类图:

208b525827a7ff1c411c_715x507.png@900-0-90-f.png
本例以使用slf4j打印为例说明。

其中org.apache.log4j.Logger和org.apache.log4j.LoggerRepository为log4j包中类。

org.slf4j.Logger为slf4j-api中类。

Log4jLoggerAdapter用于将log4j的Logger转换为slf4j的Logger,此类在slf4j包中已有,但其访问权限有限,构造函数无修饰符。需要注意。


LogService代码示意:


public class LogService
{    private org.apache.log4j.Logger logger;    private LoggerRepository loggerRepository;    /**     * Instantiates a new Oss log service.     *     * @param properties the properties     */    public LogService(Properties properties)
    {
        initEvn();        new PropertyConfigurator().doConfigure(properties, loggerRepository);
    }    /**     * Instantiates a new Oss log service.     *     * @param logFile the log file     */    public LogService(URL logFile)
    {
        initEvn();        new PropertyConfigurator().doConfigure(logFile, loggerRepository);
    }    private void initEvn()
    {        logger = new RootLogger(Level.ALL);        loggerRepository = new Hierarchy(logger);
    }    /**     * Gets logger.     *     * @param name the name     * @return the logger     */    public org.apache.log4j.Logger getLogger(String name)
    {        return loggerRepository.getLogger(name);
    }
}

MyLogFactory示例:



public final class MyLogFactory
{    private static final MyLogFactory FACTORY = new MyLogFactory();    private final Map<String, Map<String, Logger>> instances = new ConcurrentHashMap<String, Map<String, Logger>>();    private final static Map<String, LogService> SERVICES = new ConcurrentHashMap<String, LogService>();    private static final Map<String, String> APP_NAMES = new ConcurrentHashMap<String, String>();    /**     * Do configuration.     *     * @param propertiesFile the properties file     */    public static void doConfiguration(File propertiesFile)
    {        if (propertiesFile == null)
        {            return;
        }
        String serviceName = getAppName();
        LogService logService = SERVICES.get(serviceName);        if (logService == null)
        {            try            {
                logService = new LogService(propertiesFile.toURI().toURL());                SERVICES.put(serviceName, logService);
            }            catch (MalformedURLException e)
            {
                logService = new LogService(new Properties());                SERVICES.put(serviceName, logService);
            }
        }
    }    /**     * Do configuration.     *     * @param properties the properties     */    public static void doConfiguration(Properties properties)
    {        if (properties == null)
        {            return;
        }
        String serviceName = getAppName();
        LogService logService = SERVICES.get(serviceName);        if (logService == null)
        {
            logService = new LogService(properties);            SERVICES.put(serviceName, logService);
        }
    }    /**     * Gets log.     *     * @param arg0 the arg 0     * @return the log     */    public static Logger getLog(Class<?> arg0)
    {        return FACTORY.getInstance(arg0.getName());
    }    /**     * Gets logger.     *     * @param arg0 the arg 0     * @return the logger     */    public static Logger getLogger(Class<?> arg0)
    {        return FACTORY.getInstance(arg0.getName());
    }    /**     * Gets log.     *     * @param name the name     * @return the log     */    public static Logger getLog(String name)
    {        return FACTORY.getInstance(name);
    }    /**     * Gets security log.     *     * @return the security log     */    public static Logger getSecurityLog()
    {        return FACTORY.getInstance("securityLogger");
    }    /**     * Gets instance.     *     * @param name the name     * @return the instance     */    public Logger getInstance(String name)
    {
        String serviceName = getAppName();
        Map<String, Logger> logMap = instances.get(serviceName);        if (logMap == null)
        {
            logMap = new ConcurrentHashMap<String, Logger>();            instances.put(serviceName, logMap);
            Logger log = getLogByName(serviceName, name);
            logMap.put(name, log);            return log;
        }
        Logger log = logMap.get(name);        if (log == null)
        {
            log = getLogByName(serviceName, name);
            logMap.put(name, log);            return log;
        }        return log;
    }    private Logger getLogByName(String serviceName, String name)
    {
        LogService logService = SERVICES.get(serviceName);        if (null == logService)
        {            try            {
                File appRootDir = new File(getAppRoot(), "etc");
                File logProperties = new File(appRootDir, "log4j/log4j-app.properties");
                logService = new LogService(logProperties.toURI().toURL());                SERVICES.put(serviceName, logService);
            }            catch (MalformedURLException e)
            {
                logService = new LogService(new Properties());                SERVICES.put(serviceName, logService);
            }
        }
        org.apache.log4j.Logger log4jLogger = logService.getLogger(name);        return new Log4jLoggerAdapter(log4jLogger);
    }    public static String getLogHome()
    {
        ......
    }    private static String getProcessName()
    {
        ......        return ......;
    }    /**     * get app name     * @return the app name     */    public static String getAppName()
    {
        String clazzPath = "main";
        URL resourceUrl = Thread.currentThread().getContextClassLoader().getResource("/");        if (null != resourceUrl)
        {
            clazzPath = resourceUrl.getPath();
        }        if (!APP_NAMES.containsKey(clazzPath))
        {
            String appName = clazzPath.split("-")[1].split("/")[0];            APP_NAMES.put(clazzPath, appName);
        }        return APP_NAMES.get(clazzPath);
    }    private static String getAppRoot()
    {        return ... ...
    }
}



使用示例:

使用前,调用MyLogFactory.doConfiguration()将log4j.properties配置文件配置到相应webapp的logRepository中。

然后在业务类中使用Logger log = MyLogFactory.getLogger(A.class)获取日志对象,就可以正常使用了。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。