Tomcat重部署后java.util.logging日志无法持续输出到catalina.out的问题咨询
解决Tomcat热部署后java.util.logging日志不输出到catalina.out的问题
问题背景
在Tomcat(9及以上版本,Tomcat8无此问题)中首次启动Web应用时,java.util.logging.Logger的日志正常输出到catalina.out;但对运行中的Tomcat执行卸载再重新部署操作后,Logger日志转而写入日期归档日志(如catalina.2023-03-20.log),仅System.out内容仍输出到catalina.out。
原因分析
Tomcat默认使用org.apache.juli.FileHandler处理java.util.logging日志,该Handler在日志滚动或Web应用热部署时会更新关联的输出文件。热部署后,Web应用新类加载器初始化的Logger会继承已指向归档文件的全局Handler,而System.out始终绑定到当前的catalina.out流,导致日志分流。
解决方案
方案1:禁用Tomcat全局catalina日志滚动
修改Tomcat的全局日志配置,让日志始终写入catalina.out,不生成归档文件:
- 打开Tomcat安装目录下的
conf/logging.properties文件 - 找到
1catalina.org.apache.juli.FileHandler相关配置,添加或修改:1catalina.org.apache.juli.FileHandler.rotatable = false - 保存配置后重启Tomcat,后续热部署时日志将始终输出到
catalina.out。
方案2:在Web应用内配置独立的JUL日志规则
在Web应用中自定义日志配置,强制Logger输出到catalina.out:
- 在Web应用的
WEB-INF/classes目录下创建logging.properties文件,内容如下:handlers = java.util.logging.FileHandler java.util.logging.FileHandler.level = INFO java.util.logging.FileHandler.pattern = ${catalina.base}/logs/catalina.out java.util.logging.FileHandler.append = true java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter # 替换为你的Servlet全类名,关闭父Logger继承避免重复日志 test.TestLogServlet.useParentHandlers = false - 重新部署Web应用,此时应用内的Logger将直接写入
catalina.out,不受Tomcat全局日志滚动影响。
方案3:在Servlet初始化时重置Logger Handler
通过代码强制Logger输出到System.out(Tomcat已将System.out重定向到catalina.out):
修改Servlet代码如下:
package test; import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; @WebServlet(name = "TestLogServlet", urlPatterns = {"/TestLogServlet"}, loadOnStartup=1) public class TestLogServlet extends HttpServlet { private Logger logger; @Override public void init(ServletConfig config) throws ServletException { super.init(config); logger = Logger.getLogger(TestLogServlet.class.getName()); // 移除所有已绑定的Handler for (java.util.logging.Handler handler : logger.getHandlers()) { logger.removeHandler(handler); } // 创建新的ConsoleHandler并绑定到System.out ConsoleHandler consoleHandler = new ConsoleHandler(); consoleHandler.setLevel(Level.INFO); consoleHandler.setFormatter(new SimpleFormatter()); consoleHandler.setOutputStream(System.out); logger.addHandler(consoleHandler); logger.setLevel(Level.INFO); logger.setUseParentHandlers(false); System.out.println("my log message to system.out"); logger.info("my log message to logger"); } }
内容的提问来源于stack exchange,提问作者user1667016
相关产品推荐
相关产品推荐

