Resteasy 和 Google Guice:如何通过 @Injection 使用多个 @ApplicationPath 和资源?
Resteasy and Google Guice: how to use multiple @ApplicationPath and resource with @Injection?
我 created a project 使用 Resteasy 在我的 Jax-rs 资源中测试 Google Guice 提供的依赖注入。
我的意图是:
- 为我的 API 版本使用多个
@ApplicationPath
。在每个用 @ApplicationPath
注释的 class 中,我为特定版本加载一组 classes。
- 每个资源在其构造函数中都有一个
@Inject
(来自 Google Guice)以注入一些服务。
我创建了两个用 @ApplicationPath
注释的 class:ApplicationV1RS
和 ApplicationV2RS
。我在两者中都添加了相同的资源 classes(UserResource
和 HelloResource
),仅用于我的测试。
我的模块是这样配置的:
public class HelloModule implements Module
{
public void configure(final Binder binder)
{
binder.bind(IGreeterService.class).to(GreeterService.class);
binder.bind(IUserService.class).to(UserService.class);
}
}
当我调用 http://localhost:9095/v1/hello/world
或 http://localhost:9095/v2/hello/world
时,我收到相同的错误:
java.lang.RuntimeException: RESTEASY003190: Could not find constructor
for class: org.jboss.resteasy.examples.guice.hello.HelloResource
好吧,如我所料,这行不通。 Google Guice 不是 "smart" 为我使用构造器实例化资源 classes。
但是我找不到工作的方法。老实说,我真的很困惑 Google Guice、Jetty 和 Resteasy 在这种情况下如何相互配合。
如果我放弃使用 @ApplicationPath
的想法,我的资源将使用 Google Guice 配置我的 HelloModule
,如下所示:
public class HelloModule implements Module
{
public void configure(final Binder binder)
{
binder.bind(HelloResource.class);
binder.bind(IGreeterService.class).to(GreeterService.class);
binder.bind(UserResource.class);
binder.bind(IUserService.class).to(UserService.class);
}
}
但在这种情况下,我将控制权传递给 Guice 来注册我的资源(HelloResource
和 UserResource
)。它对我来说不灵活,我无法设置我的倍数 @ApplicationPath
.
那么,我缺少或不理解的是什么?
我用有问题的代码创建了一个项目。非常容易设置和测试:https://github.com/dherik/resteasy-guice-hello/tree/so-question/README.md
谢谢!
当您的应用程序中有 getClasses
方法时,它会尝试使用我们的资源 class 中缺少的默认构造函数为所有已注册资源创建实例。一种方法是创建默认构造函数并通过 setter 注入来注入依赖项。
然后在 ApplicationV1RS
和 ApplicationV2RS
中覆盖 getClasses
而不是覆盖 getSingletons
。由于 Resources 可以是 Singleton。
以下是我为使其按照您想要的方式工作而进行的更改。
ApplicationV1RS.java
@ApplicationPath("v1")
public class ApplicationV1RS extends Application {
private Set<Object> singletons = new HashSet<Object>();
public ApplicationV1RS(@Context ServletContext servletContext) {
}
@Override
public Set<Object> getSingletons() {
Injector injector = Guice.createInjector(new HelloModule());
HelloResource helloResource = injector.getInstance(HelloResource.class);
UserResource userResource = injector.getInstance(UserResource.class);
singletons.add(helloResource);
singletons.add(userResource);
return singletons;
}
}
ApplicationV2RS.java
@ApplicationPath("v2")
public class ApplicationV2RS extends Application {
private Set<Object> singletons = new HashSet<Object>();
public ApplicationV2RS(@Context ServletContext servletContext) {
}
@Override
public Set<Object> getSingletons() {
Injector injector = Guice.createInjector(new HelloModule());
HelloResource helloResource = injector.getInstance(HelloResource.class);
UserResource userResource = injector.getInstance(UserResource.class);
singletons.add(helloResource);
singletons.add(userResource);
return singletons;
}
}
HelloResource.java
@Path("hello")
public class HelloResource {
@Inject
private IGreeterService greeter;
public HelloResource() {
}
@GET
@Path("{name}")
public String hello(@PathParam("name") final String name) {
return greeter.greet(name);
}
}
UserResource.java
@Path("user")
public class UserResource {
@Inject
private IUserService userService;
public UserResource() {
}
@GET
@Path("{name}")
public String hello(@PathParam("name") final String name) {
return userService.getUser(name);
}
}
将 @Singleton
添加到您的服务 类。
希望对您有所帮助。
我也把代码推到了forked repo。看看
我 created a project 使用 Resteasy 在我的 Jax-rs 资源中测试 Google Guice 提供的依赖注入。
我的意图是:
- 为我的 API 版本使用多个
@ApplicationPath
。在每个用@ApplicationPath
注释的 class 中,我为特定版本加载一组 classes。 - 每个资源在其构造函数中都有一个
@Inject
(来自 Google Guice)以注入一些服务。
我创建了两个用 @ApplicationPath
注释的 class:ApplicationV1RS
和 ApplicationV2RS
。我在两者中都添加了相同的资源 classes(UserResource
和 HelloResource
),仅用于我的测试。
我的模块是这样配置的:
public class HelloModule implements Module
{
public void configure(final Binder binder)
{
binder.bind(IGreeterService.class).to(GreeterService.class);
binder.bind(IUserService.class).to(UserService.class);
}
}
当我调用 http://localhost:9095/v1/hello/world
或 http://localhost:9095/v2/hello/world
时,我收到相同的错误:
java.lang.RuntimeException: RESTEASY003190: Could not find constructor
for class: org.jboss.resteasy.examples.guice.hello.HelloResource
好吧,如我所料,这行不通。 Google Guice 不是 "smart" 为我使用构造器实例化资源 classes。
但是我找不到工作的方法。老实说,我真的很困惑 Google Guice、Jetty 和 Resteasy 在这种情况下如何相互配合。
如果我放弃使用 @ApplicationPath
的想法,我的资源将使用 Google Guice 配置我的 HelloModule
,如下所示:
public class HelloModule implements Module
{
public void configure(final Binder binder)
{
binder.bind(HelloResource.class);
binder.bind(IGreeterService.class).to(GreeterService.class);
binder.bind(UserResource.class);
binder.bind(IUserService.class).to(UserService.class);
}
}
但在这种情况下,我将控制权传递给 Guice 来注册我的资源(HelloResource
和 UserResource
)。它对我来说不灵活,我无法设置我的倍数 @ApplicationPath
.
那么,我缺少或不理解的是什么?
我用有问题的代码创建了一个项目。非常容易设置和测试:https://github.com/dherik/resteasy-guice-hello/tree/so-question/README.md
谢谢!
当您的应用程序中有 getClasses
方法时,它会尝试使用我们的资源 class 中缺少的默认构造函数为所有已注册资源创建实例。一种方法是创建默认构造函数并通过 setter 注入来注入依赖项。
然后在 ApplicationV1RS
和 ApplicationV2RS
中覆盖 getClasses
而不是覆盖 getSingletons
。由于 Resources 可以是 Singleton。
以下是我为使其按照您想要的方式工作而进行的更改。
ApplicationV1RS.java
@ApplicationPath("v1")
public class ApplicationV1RS extends Application {
private Set<Object> singletons = new HashSet<Object>();
public ApplicationV1RS(@Context ServletContext servletContext) {
}
@Override
public Set<Object> getSingletons() {
Injector injector = Guice.createInjector(new HelloModule());
HelloResource helloResource = injector.getInstance(HelloResource.class);
UserResource userResource = injector.getInstance(UserResource.class);
singletons.add(helloResource);
singletons.add(userResource);
return singletons;
}
}
ApplicationV2RS.java
@ApplicationPath("v2")
public class ApplicationV2RS extends Application {
private Set<Object> singletons = new HashSet<Object>();
public ApplicationV2RS(@Context ServletContext servletContext) {
}
@Override
public Set<Object> getSingletons() {
Injector injector = Guice.createInjector(new HelloModule());
HelloResource helloResource = injector.getInstance(HelloResource.class);
UserResource userResource = injector.getInstance(UserResource.class);
singletons.add(helloResource);
singletons.add(userResource);
return singletons;
}
}
HelloResource.java
@Path("hello")
public class HelloResource {
@Inject
private IGreeterService greeter;
public HelloResource() {
}
@GET
@Path("{name}")
public String hello(@PathParam("name") final String name) {
return greeter.greet(name);
}
}
UserResource.java
@Path("user")
public class UserResource {
@Inject
private IUserService userService;
public UserResource() {
}
@GET
@Path("{name}")
public String hello(@PathParam("name") final String name) {
return userService.getUser(name);
}
}
将 @Singleton
添加到您的服务 类。
希望对您有所帮助。
我也把代码推到了forked repo。看看