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

时间:2016-09-13 03:08:29

标签: jax-rs guice resteasy embedded-jetty

created a project使用Resteasy测试Google Guice在我的Jax-rs资源中提供的依赖注入。

我的意图是:

  • 对我的API版本使用多个@ApplicationPath。在每个用@ApplicationPath注释的类中,我为特定版本加载了一组类。
  • 每个资源在其构造函数中都有@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);
   }
}

当我致电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

好吧,正如我所料,这不起作用。对于我来说,使用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);
   }
}

但是在这种情况下,我正在传递控件以将我的资源(HelloResourceUserResource)注册到Guice。它对我来说不灵活,我无法设置我的多个@ApplicationPath

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

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

谢谢!

1 个答案:

答案 0 :(得分:1)

当你的应用程序中有getClasses方法时,它会尝试使用我们的Resources类中缺少的默认构造函数为所有已注册的资源创建实例。一种方法是创建默认构造函数并通过setter Injection注入依赖项。 然后,不要覆盖ApplicationV1RSApplicationV2RS中的getSingletons,而是覆盖@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; } } 。由于资源可以是Singleton。

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

  

ApplicationV1RS.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;
    }
}
  

ApplicationV2RS.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);
    }
}
  

HelloResource.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);
    }
}
  

UserResource.java

@Singleton

将{{1}}添加到您的服务类。

希望它有所帮助。

我还将代码推送到forked repo。检查出来