问题描述
我创建了一个项目以测试提供的依赖项注入由Google Guice在我的Jax-rs资源中,使用Resteasy.
I created a project to test the dependency injection offered by Google Guice in my Jax-rs resources, using Resteasy.
我的意图是:
- 对我的API版本使用多个
@ApplicationPath
.在每个用@ApplicationPath
注释的类中,我为特定版本加载了一组类. - 每个资源的构造函数中都有一个
@Inject
(来自Google Guice),以注入一些服务.
- Use multiple
@ApplicationPath
for the versions of my API. In each class annotated with@ApplicationPath
I load a set of classes for the specific version. - Each resource have a
@Inject
(from Google Guice) in his constructor to inject some services.
我创建了两个用@ApplicationPath
注释的类:ApplicationV1RS
和ApplicationV2RS
.在这两种方法中,我都添加了相同的资源类(UserResource
和HelloResource
),仅用于测试.
I created two classes annotated with @ApplicationPath
: ApplicationV1RS
and ApplicationV2RS
. In both I added the same resources classes (UserResource
and HelloResource
), only for my test.
我的模块的配置如下:
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
时,我收到相同的错误:
When I call http://localhost:9095/v1/hello/world
or http://localhost:9095/v2/hello/world
, I receive the same error:
java.lang.RuntimeException: RESTEASY003190: Could not find constructor
for class: org.jboss.resteasy.examples.guice.hello.HelloResource
嗯,正如我所料,这是行不通的. Google Guice对我而言,使用构造函数实例化资源类不是聪明"的事情.
Well, as I expected, this not works. The Google Guice is not "smart" to instantiate the resource classes using the construtor for me.
但是我找不到工作的方法.老实说,我很困惑Google Guice,Jetty和Resteasy在这种情况下如何相互配合.
But I can't find a way to work. To be really honest, I'm really confuse about how the Google Guice, Jetty and Resteasy play with each other in this scenario.
如果我放弃使用@ApplicationPath
的想法,那么我的资源将与Google Guice一起配置HelloModule
,如下所示:
If I abandon the idea of use @ApplicationPath
, my resources work with Google Guice configuring my HelloModule
like this:
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);
}
}
但是在这种情况下,我正在传递控件以将我的资源(HelloResource
和UserResource
)注册到Guice.这对我来说并不灵活,我无法设置多个@ApplicationPath
.
But in this case, I'm passing the control to register my resources (HelloResource
and UserResource
) to Guice. It's not flexible for me, I can't setup my multiple @ApplicationPath
.
那么,我缺少或不了解的内容是什么?
So, what I'm missing or not understanding?
我用有问题的代码创建了一个项目.设置和测试非常容易: https://github .com/dherik/resteasy-guice-hello/tree/so-question/README.md
I created a project with the problemetic code. Is very easy to setup and test: https://github.com/dherik/resteasy-guice-hello/tree/so-question/README.md
谢谢!
推荐答案
当您的应用程序中具有getClasses
方法时,它会尝试使用资源类中缺少的默认构造函数为所有已注册资源创建实例.一种方法是创建一个默认构造函数,然后通过setter Injection注入依赖项.然后,您将覆盖getSingletons
,而不是覆盖ApplicationV1RS
和ApplicationV2RS
中的getClasses
.由于资源可以是单身人士.
When you have getClasses
method in your Application then it tries to create instance for all the registered resources using the default constructor which is missing in our Resources class. One way is to create a default constructor and Inject the dependencies through setter Injection.And then instead of overriding getClasses
in ApplicationV1RS
and ApplicationV2RS
you override getSingletons
. Since Resources can be Singleton.
下面是为使它按您希望的方式工作而进行的更改.
Below are the changes that I made to make it work the way you want.
@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;
}
}
@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;
}
}
@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);
}
}
@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
.
Add @Singleton
to your Service Classes.
希望有帮助.
我也将代码推送到了分叉存储库.看看
I have also pushed the code to forked repo. check it out
这篇关于Resteasy和Google Guice:如何在@Injection中使用多个@ApplicationPath和资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!