Resteasy和Google Guice:如何在@Injection中使用多个@ApplicationPath和资源?

Dhe*_*rik 8 jax-rs guice embedded-jetty resteasy

我使用Resteasy 创建了一个项目来测试Google Guice在我的Jax-rs资源中提供的依赖注入.

我的意图是:

  • @ApplicationPath对我的API版本使用multiple .在每个用@ApplicationPathI 注释的类中,为特定版本加载一组类.
  • 每个资源都有一个@Inject(来自Google Guice)在他的构造函数中注入一些服务.

我创建了两个带有注释的类@ApplicationPath:ApplicationV1RSApplicationV2RS.在这两个中我添加了相同的资源类(UserResourceHelloResource),仅用于我的测试.

我的模块配置如下:

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);
   }
}
Run Code Online (Sandbox Code Playgroud)

当我打电话http://localhost:9095/v1/hello/worldhttp://localhost:9095/v2/hello/world,我收到同样的错误:

java.lang.RuntimeException: RESTEASY003190: Could not find constructor 
    for class: org.jboss.resteasy.examples.guice.hello.HelloResource
Run Code Online (Sandbox Code Playgroud)

好吧,正如我所料,这不起作用.对于我来说,使用construtor实例化资源类并不是"聪明"的.

但我找不到办法.说实话,我真的很困惑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);
   }
}
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,我通过控件将我的资源(HelloResourceUserResource)注册到Guice.它对我来说不灵活,我无法设置我的倍数@ApplicationPath.

那么,我缺少什么或不理解?

我用问题代码创建了一个项目.设置和测试非常简单:https://github.com/dherik/resteasy-guice-hello/tree/so-question/README.md

谢谢!

Dee*_*arg 1

当您的应用程序中有getClasses方法时,它会尝试使用我们的资源类中缺少的默认构造函数为所有注册的资源创建实例。一种方法是创建默认构造函数并通过 setter 注入注入依赖项。然后你不是重写getClassesinApplicationV1RS而是ApplicationV2RS重写getSingletons. 由于资源可以是单例的。

以下是我为使其按照您想要的方式工作而所做的更改。

应用程序V1RS.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

应用程序V2RS.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用户资源.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);
    }
}
Run Code Online (Sandbox Code Playgroud)

添加@Singleton到您的服务类别。

希望能帮助到你。

我还将代码推送到了forked repo。一探究竟