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

基础Weld示例搭配Embedded Tomcat无法运行:注入Bean为空、BeanManager查找失败

问题根源

从日志差异能明确看出:Embedded Tomcat环境下Weld没有触发Tomcat专属容器集成逻辑,而是回退到了通用Servlet生命周期管理模式。这直接导致Weld无法把BeanManager正确绑定到JNDI,也没法处理CDI依赖注入,最终出现Bean注入为null、JNDI查找失败的问题。

解决方案

1. 替换Weld依赖,启用Tomcat集成模块

你之前用的weld-servlet-core仅包含核心Servlet支持,缺少Tomcat集成的关键代码。必须替换为完整的weld-servlet依赖:

implementation group: 'org.jboss.weld.servlet', name: 'weld-servlet', version: '5.1.0.Final'

2. 确保Weld能识别Embedded Tomcat环境

Embedded Tomcat的类加载机制和常规Tomcat不同,得让Weld能检测到Tomcat核心类(比如org.apache.catalina.Context):

  • 添加Tomcat API依赖(保证Weld能访问到Tomcat类):
compileOnly group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '10.1.5'
compileOnly group: 'org.apache.tomcat', name: 'tomcat-catalina', version: '10.1.5'
  • 若自动检测失效,强制Weld使用Tomcat容器:
    在启动Tomcat前添加系统属性:
System.setProperty("org.jboss.weld.environment.container.class", "org.jboss.weld.environment.tomcat.TomcatContainer");

3. 调整Embedded Tomcat的类加载器和监听器配置

修改主类代码,确保Web应用类加载器能加载Weld的Tomcat集成类,同时使用正确的Weld监听器:

Tomcat tomcat = new Tomcat();
String webappDirLocation = "src/main/webapp/";
Context ctx = tomcat.addWebapp("/", new File(webappDirLocation).getAbsolutePath());

// 设置Web应用类加载器为当前线程类加载器,确保Weld能访问到Tomcat和自身的类
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
ctx.setClassLoader(classLoader);

File additionWebInfClasses = new File("build/classes/java/main/");
WebResourceRoot webResourceRoot = new StandardRoot(ctx);
webResourceRoot.addPreResources(
        new DirResourceSet(webResourceRoot, "/WEB-INF/classes", additionWebInfClasses.getAbsolutePath(), "/"));

// 替换为Weld Tomcat专属监听器
ctx.addApplicationListener("org.jboss.weld.environment.tomcat.WeldServletListener");

tomcat.enableNaming();
// 手动添加BeanManager的JNDI资源链接(Embedded Tomcat不会自动加载context.xml配置)
ctx.getNamingResources().addResourceLink(new ResourceLink() {{
    setName("BeanManager");
    setGlobal("BeanManager");
    setType("jakarta.enterprise.inject.spi.BeanManager");
}});

tomcat.getConnector();
tomcat.start();
tomcat.getServer().await();

4. 检查beans.xml的兼容性

确保WEB-INF下的beans.xml使用Jakarta EE 9+的命名空间(适配Tomcat10和Weld5):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
       version="4.0"
       bean-discovery-mode="all">
</beans>
验证

启动后查看日志,若出现org.jboss.weld.environment.tomcat.TomcatContainer initialize的条目,说明Weld已正确识别Tomcat环境,此时Bean注入和JNDI查找BeanManager应该能正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 17:40:39