栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Tomcat日志记录混乱

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Tomcat日志记录混乱

如果我正确理解,您最终将获得如下所示的日志记录属性:

java.util.logging.ConsoleHandler.level = FINERorg.apache.catalina.realm.level = FINER

在Java记录概述部分1.1规定:

应用程序在Logger对象上进行日志记录调用。记录器以分层的名称空间组织,子记录器可以从名称空间的父级继承一些记录属性。

读取记录器名称时,父记录器位于圆点的左侧。所以,

org.apache.catalina
是的父
org.apache.catalina.realm
org.apache.catalina.core

执行代码必须要求记录器才能存在。 仅在属性文件中添加行不会创建记录器。
如果这样做的话,他们无论如何都会被垃圾收集。这意味着您拥有一个记录器树

A<- B <- C
。您要为此设置
B
所有
B
子级的级别,以便
A.B.level
在属性文件中添加行。然而,在运行时所要求的记录器
A
C

因此,您所需要的

"" <- A <- A.B.C
就是期望
"" <- A <- A.B <- A.B.C

综上所述,我认为您的记录器在运行时如下所示:

"" <- org.apache.catalina <-org.apache.catalina.realm.Realmbase
而且还没有Tomcat代码创建名为的实际记录器
org.apache.catalina.realm

您可以通过将JConsole连接到运行中的JVM并检查MBean选项卡并列出记录器名称来进行验证。在Tomcat上,这将不起作用,因为返回的记录器取决于调用的类加载器。

要解决此问题,您可以使用config选项来要求并保持记录器在内存中。您只需将其安装在系统类路径上的自定义代码上。

否则,您必须在属性文件中指定所有已知的子记录器名称,这些名称可能很冗长。

第一个想法:如果我们看一下CSS的特殊性,我们知道.mydiv {color:red}不如div.mydiv
{color:green}那样具体,那么div.mydiv包含红色文本吗?继承是指(如果未指定)什么是反继承。

与CSS不同,JUL具有运行时记录器树和属性文件。当执行代码需要记录器时,将动态调整运行时记录器树。仅当代码需要记录器时才使用这些属性。除非通过代码创建记录器,否则在属性文件中指定记录器名称并不重要。这可以更改记录器的父级,从而更改级别。试一下:

package so;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.Properties;import java.util.logging.Level;import java.util.logging.LogManager;import java.util.logging.Logger;public class TheMissingParent {    private static final Logger[] LAZY_ONE;    static {        LAZY_ONE = new Logger[] { Logger.getLogger("org.apache.catalina"),     Logger.getLogger("org.apache.catalina.realm.Realmbase") };    }    private static volatile Logger[] LAZY_TWO;    public static void main(String[] args) {        loadProperties();        printAncestors(LAZY_ONE);        findlLongLostParents();        System.out.println("====");        printAncestors(LAZY_ONE);    }    private static void loadProperties() {        Properties props = new Properties();        props.put("org.apache.catalina.realm.level", "FINER");        try(ByteArrayOutputStream out = new ByteArrayOutputStream()) { props.store(out, ""); LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));        } catch (IOException ioe) { throw new AssertionError(ioe);        }    }    private static void findlLongLostParents() {        LAZY_TWO = new Logger[] {Logger.getLogger("org.apache.catalina.realm") };    }    private static void printAncestors(Logger[] loggers) {        // System.out.println(loggers.toString());        for (Logger l : loggers) { printAncestors(l); System.out.println();        }    }    private static void printAncestors(Logger l) {        if (l != null) { printAncestors(l.getParent()); System.out.print("<-"); String name = l.getName(); if (name != null && name.isEmpty()) {     System.out.append(""""); } else {     System.out.append(name); } for(Logger p = l; p != null; p = p.getParent()) {     Level lvl = p.getLevel();     if (lvl != null) {         System.out.append('{').append(lvl.getName()).append('}');         break;     } }        }    }}

这将输出:

<-""{INFO}<-org.apache.catalina{INFO}<-""{INFO}<-org.apache.catalina{INFO}<-org.apache.catalina.realm.Realmbase{INFO}====<-""{INFO}<-org.apache.catalina{INFO}<-""{INFO}<-org.apache.catalina{INFO}<-org.apache.catalina.realm{FINER}<-org.apache.catalina.realm.Realmbase{FINER}

这是核心问题。如果Tomcat(或某些自定义代码)从不要求

org.apache.catalina.realm
记录器,则属性文件中的行就是无效代码。

其次,如果您这样说,那么没有人将org.apache.catalina或org.apache或org
nor指定为``级别INFO’‘,那么INFO的价值从何而来?

该行为在LoggerManager类级别docs中进行了描述:

如果这两个属性均未定义,则如上所述,LogManager将从JRE目录中的属性文件“ lib /
logging.properties”中读取其初始配置。

名为空字符串的根记录器

""
是所有记录器的父级。始终创建根记录器。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/468889.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号