Tomcat10+Resteasy+CDI环境启动报错RESTEASY003190:找不到类构造方法
问题原因
RESTEASY003190: Could not find constructor for class: com.cdi.GreetingResource 异常的核心原因:
- 当Resteasy未与CDI正确集成时,会尝试通过反射直接实例化JAX-RS资源类,此时要求类必须提供公共无参构造函数。你的
GreetingResource仅包含带@Inject注解的构造函数,没有无参构造,导致反射实例化失败。 - 另一个可能是CDI(Weld)配置不完整,容器未扫描并管理
GreetingResource,Resteasy无法通过CDI获取已注入依赖的实例。
解决方案
方案一:添加无参构造函数(快速临时修复)
给GreetingResource添加公共无参构造函数,让Resteasy可以直接反射实例化:
package com.cdi; import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; @Path("/greet") public class GreetingResource { private final GreetingService greetingService; @Inject public GreetingResource(GreetingService greetingService) { this.greetingService = greetingService; } // 添加公共无参构造函数 public GreetingResource() { // CDI接管实例化时不会调用此构造,可留空或初始化默认值 this.greetingService = null; } @GET public String get() { greetingService.setName("bruno"); greetingService.createMessage(); return greetingService.getMessage(); } }
方案二:正确集成Resteasy与CDI(推荐规范做法)
Tomcat是轻量Servlet容器,需手动配置CDI与Resteasy的集成,让CDI接管资源类的实例化和依赖注入:
1. 添加Resteasy-CDI集成依赖
确保Maven(或Gradle)中包含Resteasy的CDI集成包:
<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-cdi</artifactId> <version>6.2.8.Final</version> <scope>compile</scope> </dependency>
2. 启用CDI扫描
在WEB-INF/beans.xml中配置CDI扫描规则(不存在则创建):
<?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="annotated"> </beans>
bean-discovery-mode="annotated"表示仅扫描带有CDI注解(如@RequestScoped、@Inject)的类,适配你的代码场景。
3. 配置Resteasy启用CDI集成
在web.xml中给Resteasy Servlet添加resteasy.cdi.integration参数:
<servlet> <servlet-name>Resteasy</servlet-name> <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> <init-param> <param-name>resteasy.servlet.mapping.prefix</param-name> <param-value>/api</param-value> </init-param> <init-param> <param-name>resteasy.cdi.integration</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Resteasy</servlet-name> <url-pattern>/api/*</url-pattern> </servlet-mapping>
4. 给资源类添加CDI作用域注解
给GreetingResource添加@RequestScoped注解,让CDI将其纳入管理:
package com.cdi; import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.enterprise.context.RequestScoped; @Path("/greet") @RequestScoped // 添加CDI请求作用域注解 public class GreetingResource { private final GreetingService greetingService; @Inject public GreetingResource(GreetingService greetingService) { this.greetingService = greetingService; } @GET public String get() { greetingService.setName("bruno"); greetingService.createMessage(); return greetingService.getMessage(); } }
完成以上配置后,CDI会负责创建GreetingResource实例并注入GreetingService,Resteasy将从CDI容器中获取实例,无需无参构造函数即可正常运行。
内容的提问来源于stack exchange,提问作者Bruno Rozendo
相关产品推荐
相关产品推荐

