本文介绍了Resteasy和Google Guice:如何在@Injection中使用多个@ApplicationPath和资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

创建了一个项目以测试提供的依赖项注入由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注释的类:ApplicationV1RSApplicationV2RS.在这两种方法中,我都添加了相同的资源类(UserResourceHelloResource),仅用于测试.

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/worldhttp://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);
   }
}

但是在这种情况下,我正在传递控件以将我的资源(HelloResourceUserResource)注册到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,而不是覆盖ApplicationV1RSApplicationV2RS中的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和资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 05:17