You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入式Tomcat中如何访问Servlet Context外部声明的静态变量?

问题根本原因

该问题是类加载器隔离导致的:
嵌入式Tomcat默认会为部署的Web应用创建独立的WebAppClassLoader,你项目里的Main类是由JVM系统类加载器加载的,而带@WebServlet注解的Servlet类是由Tomcat的Web应用类加载器加载的。不同类加载器加载的全限定名相同的类会被JVM识别为两个不同的类,各自的静态变量完全独立互不影响,所以你在main方法里操作的是系统类加载器加载的Main类的静态变量,Servlet里访问的是WebAppClassLoader加载的Main类的静态变量,自然拿到的是初始值0。

可行解决方案

方案1:关闭Tomcat Web应用类加载器隔离(最简单)

直接配置Tomcat使用系统类加载器加载Web应用的所有类,避免出现两份类实例,在tomcat.start()前添加一行配置即可:

public static void main(String[] args){
  list.add(new Object());
  tomcat = new Tomcat();
  tomcat.setPort(8080);  
  // 新增这一行,指定Web应用使用系统类加载器
  tomcat.getHost().setClassLoader(ClassLoader.getSystemClassLoader());
  try {
      tomcat.start();
      tomcat.getServer().await();
  } catch (Exception e) {
      e.printStackTrace();
  }        
}

方案2:使用ServletContext共享数据(符合Servlet规范的标准做法)

静态变量跨类加载器共享本身就不符合容器设计规范,推荐将共享数据存入ServletContext全局上下文:

  1. 启动Tomcat时往上下文里存入共享集合
// 注册Web应用上下文
Context context = tomcat.addContext("", System.getProperty("java.io.tmpdir"));
// 把list存入上下文
context.setAttribute("sharedList", list);
// 注册Servlet
Tomcat.addServlet(context, "servlet name", new ServletClass());
context.addServletMappingDecoded("/test", "servlet name");
  1. Servlet中从上下文取数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    List<Object> list = (List<Object>) getServletContext().getAttribute("sharedList");
    System.out.println("LIST SIZE: " + list.size());
}

修改后即可拿到预期的大小1。

内容的提问来源于stack exchange,提问作者nadhem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 00:36:04