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

升级技术栈后CDI注入返回NULL问题求助

Tomcat 10.1 + Jakarta EE 升级后CDI注入NULL问题解决指南

核心问题定位

从Java EE 8/Tomcat9/Java8升级到Jakarta EE/Tomcat10.1/Java21后,CDI注入失效的核心原因通常是新旧API包名混用、CDI容器未正确初始化,或是JAX-RS与CDI集成配置缺失。以下是针对性的解决方案:


第一步:统一CDI实现(二选一,不要混用)

Tomcat本身不自带CDI容器,必须手动引入实现,Weld和OpenWebBeans都可兼容Jakarta EE 10,选其一即可。

方案一:使用Weld Servlet(生态更成熟)

  1. Maven依赖配置(确保是Jakarta版本)
<dependency>
    <groupId>org.jboss.weld.servlet</groupId>
    <artifactId>weld-servlet-shaded</artifactId>
    <version>5.1.2.Final</version> <!-- 匹配Jakarta EE 10与Tomcat10.1 -->
    <scope>runtime</scope>
</dependency>
  1. 初始化CDI容器
    • 方式1:修改web.xml添加监听器
    <listener>
        <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
    </listener>
    <resource-env-ref>
        <description>CDI Bean Manager工厂</description>
        <resource-env-ref-name>BeanManager</resource-env-ref-name>
        <resource-env-ref-type>jakarta.enterprise.inject.spi.BeanManager</resource-env-ref-type>
    </resource-env-ref>
    
    • 方式2:代码注解式初始化(无需修改web.xml)
    @WebListener
    public class WeldInitListener extends org.jboss.weld.environment.servlet.Listener {}
    
  2. beans.xml配置(放在src/main/resources/META-INF/下,必须用Jakarta命名空间)
<?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"
       discovery-mode="all">
</beans>

方案二:使用OpenWebBeans

  1. Maven依赖配置
<dependency>
    <groupId>org.apache.openwebbeans</groupId>
    <artifactId>openwebbeans-servlet</artifactId>
    <version>4.0.2</version> <!-- 兼容Jakarta EE 10 -->
    <scope>runtime</scope>
</dependency>
<!-- 若需JAX-RS集成,额外添加 -->
<dependency>
    <groupId>org.apache.openwebbeans</groupId>
    <artifactId>openwebbeans-jaxrs</artifactId>
    <version>4.0.2</version>
    <scope>runtime</scope>
</dependency>
  1. web.xml配置
<listener>
    <listener-class>org.apache.webbeans.servlet.WebBeansConfigurationListener</listener-class>
</listener>
<listener>
    <listener-class>org.apache.webbeans.servlet.WebBeansServletContextListener</listener-class>
</listener>
<resource-env-ref>
    <resource-env-ref-name>BeanManager</resource-env-ref-name>
    <resource-env-ref-type>jakarta.enterprise.inject.spi.BeanManager</resource-env-ref-type>
</resource-env-ref>
  1. beans.xml配置与Weld方案一致,必须使用Jakarta命名空间。

第二步:关键检查点(必做)

  1. 彻底替换javax为jakarta注解
    所有CDI、JAX-RS相关注解必须是Jakarta包下的:

    • @ApplicationScoped → jakarta.enterprise.context.ApplicationScoped
    • @Inject → jakarta.inject.Inject
    • @Path/@GET → jakarta.ws.rs.Path/jakarta.ws.rs.GET
      混用javax和jakarta注解会直接导致CDI容器无法识别Bean。
  2. 清理残留的javax依赖
    检查Maven依赖树,确保所有旧Java EE依赖(如javax.servlet-api、javax.ws.rs-api)已替换为Jakarta版本(jakarta.servlet-api、jakarta.ws.rs-api)。

  3. JAX-RS与CDI集成配置
    若使用Jersey作为JAX-RS实现,需添加CDI集成依赖:

<dependency>
    <groupId>org.glassfish.jersey.ext.cdi</groupId>
    <artifactId>jersey-cdi1x</artifactId>
    <version>3.1.5</version> <!-- 匹配Jakarta EE 10 -->
</dependency>

确保JAX-RS资源类被CDI容器管理,否则@Inject不会生效。

  1. 验证CDI容器初始化
    启动Tomcat后查看日志:
    • Weld会输出WELD-000900: 5.1.2.Final (Final)
    • OpenWebBeans会输出OpenWebBeans Container is starting...
      无相关日志则说明容器未正确初始化,需检查依赖或监听器配置。

验证方法

在MyService中添加@PostConstruct方法,启动后查看控制台输出:

@PostConstruct
public void init() {
    System.out.println("MyService已被CDI容器初始化");
}

若未输出该日志,说明Bean未被CDI识别,需回头检查注解包名和beans.xml配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:35:07