基于Jersey、Hibernate实现JAX-RS遇WELD-001408依赖注入问题求助
我之前在整合Jersey、Hibernate和DataSource做JAX-RS服务时,也碰到过几乎一模一样的报错,核心原因就是Jersey的MVC模块和CDI(Weld)的集成出了问题,导致ViewableMessageBodyWriter里的ServiceLocator找不到合适的注入实例。下面是我亲测有效的几个解决步骤:
1. 检查并添加Jersey-CDI集成依赖
首先要确保你的项目里包含了Jersey和CDI集成的专用模块,不同环境(Java EE容器/SE环境)依赖略有不同:
- 如果是Java EE容器(比如WildFly、TomEE),添加Maven依赖:
<dependency> <groupId>org.glassfish.jersey.ext.cdi</groupId> <artifactId>jersey-cdi1x</artifactId> <version>你的Jersey核心版本</version> <scope>runtime</scope> </dependency> - 如果是SE环境,换成
jersey-weld2-se依赖:<dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-weld2-se</artifactId> <version>你的Jersey核心版本</version> </dependency>
⚠️ 重点:依赖版本必须和你使用的Jersey核心版本完全一致,否则会出现版本冲突。
2. 确保CDI被正确激活
CDI需要一个beans.xml文件来触发扫描和激活,哪怕是空文件也可以:
在WEB-INF目录下创建beans.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <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_1_1.xsd" bean-discovery-mode="all"> </beans>
bean-discovery-mode="all"会让CDI扫描所有类,避免漏掉需要注入的组件。
3. 排除重复的Weld依赖(容器环境专属)
如果你的应用运行在自带Weld的服务器(比如WildFly)上,手动引入的Jersey-CDI依赖可能会和服务器自带的Weld版本冲突,需要排除重复依赖:
<dependency> <groupId>org.glassfish.jersey.ext.cdi</groupId> <artifactId>jersey-cdi1x</artifactId> <version>你的Jersey核心版本</version> <scope>runtime</scope> <exclusions> <exclusion> <groupId>org.jboss.weld</groupId> <artifactId>weld-core</artifactId> </exclusion> <exclusion> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-core</artifactId> </exclusion> </exclusions> </dependency>
4. 确认Jersey初始化方式正确
如果是用ResourceConfig配置Jersey,记得给它加上@ApplicationScoped注解,让CDI能够管理这个配置类:
@ApplicationScoped public class MyJerseyApp extends ResourceConfig { public MyJerseyApp() { packages("你的REST接口包路径"); // 其他配置... } }
如果是用web.xml配置Jersey Servlet,确保参数指向正确的配置类:
<servlet> <servlet-name>Jersey REST Service</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>com.yourpackage.MyJerseyApp</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
本质上这个错误就是CDI容器找不到ServiceLocator的实例,而Jersey的MVC模块又依赖它完成视图渲染。按照上面的步骤逐一排查依赖、CDI激活状态和Jersey配置,应该就能解决问题。
内容的提问来源于stack exchange,提问作者Felipe Junges

