Tomcat 8上JSF 2.3的CDI注入失效,求排查解决方法
我来帮你排查这个@Inject报错的问题——按BalusC的教程部署Weld后还遇到这个错,大概率是几个容易忽略的配置点没做好,咱们一步步来梳理:
1. 确认你的Bean被CDI识别
首先,你的ConfigurationBean有没有添加CDI的bean定义注解?CDI不会自动把普通Java类当作可注入的bean,必须给它加上比如@Named、@ApplicationScoped、@RequestScoped这类注解(或者自定义的stereotype注解)。举个正确的示例:
import javax.enterprise.context.ApplicationScoped; import javax.inject.Named; @Named @ApplicationScoped public class ConfigurationBean { // 你的业务代码 }
如果没有这些注解,哪怕你部署了Weld,CDI也找不到这个bean,自然会报“no bean matches the injection point”。
2. 检查beans.xml的配置和位置
Tomcat下使用Weld,beans.xml必须放在WEB-INF目录下,而且核心配置要正确,特别是bean-discovery-mode属性:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd" version="2.0" bean-discovery-mode="all"> </beans>
- 如果
bean-discovery-mode设为annotated,只有带CDI注解的类才会被扫描;如果是all,则会扫描所有类(适合调试阶段快速验证)。如果你的ConfigurationBean没加注解,又用了annotated模式,肯定找不到。 - 注意
beans.xml的版本要和Weld版本匹配:Weld 3.x对应CDI 2.0,所以version设为2.0是正确的。
3. 验证Weld和JSF的依赖是否正确
- Weld依赖:Tomcat本身不提供CDI,所以你需要把Weld Servlet的jar包放到
WEB-INF/lib下。如果用Maven,依赖应该是:
<dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-core</artifactId> <version>3.1.9.Final</version> <!-- 选择和JSF2.3兼容的3.x系列版本 --> </dependency>
确保scope是compile(默认就是),这样Maven会把jar包打包到项目里。
- JSF依赖:要用支持CDI的JSF 2.3实现,比如Mojarra 2.3.x。Maven依赖示例:
<dependency> <groupId>org.glassfish</groupId> <artifactId>javax.faces</artifactId> <version>2.3.17</version> </dependency>
不要把JSF的jar包放到Tomcat的lib目录下,避免类加载冲突,全部放在项目的WEB-INF/lib里。
4. 检查JSF的faces-config.xml配置
确保faces-config.xml的版本是2.3,并且添加Weld的EL解析器,让JSF能正确调用CDI的bean:
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd" version="2.3"> <application> <el-resolver>org.jboss.weld.el.WeldELResolver</el-resolver> </application> </faces-config>
这个解析器能让JSF的EL表达式正确找到CDI注入的bean,也能避免一些注入时的类加载问题。
5. 确认注入点的类型匹配
如果你是注入接口类型,比如:
@Inject private MyConfigInterface config;
那必须确保MyConfigInterface的实现类(比如你的ConfigurationBean)添加了CDI注解,否则CDI找不到对应的实现类。如果是注入具体类,要确保这个类没有被排除在扫描之外。
6. 排查类加载冲突
检查WEB-INF/lib里有没有重复的jar包,比如多个版本的Weld、JSF或者CDI相关的jar。另外,Tomcat的lib目录里如果有其他JSF或者CDI的jar包,也会导致冲突,要把这些多余的jar删掉,确保所有依赖都在项目内部。
内容的提问来源于stack exchange,提问作者Christian Ibanibo

