39

Jersey 通常使用 HK2 依赖注入,但我想将 Jersey 与 Dagger 2 一起使用。Dagger 和 HK2 都实现了 JSR 330,我已经将其作为证据表明这应该是可能的,无需太多努力。我找到了让 Jersey 与 CDI(例如 Weld)、Spring DI 和 Guice 一起工作的方法,但我在 Dagger 上找不到任何东西。

提供一些上下文:我在 SE 环境中运行 Grizzly–Jersey 服务器,而不是在 EE 容器中。我的 Maven 项目有com.google.dagger:daggerorg.glassfish.jersey.containers:jersey-container-grizzly2-http作为依赖项,但没有 org.glassfish.jersey.inject:jersey-hk2,因为我想用 Dagger 替换 HK2。

资源类如下所示:

@Path("/example")
public final class ExampleResource {

    private final Dependency dependency;

    @Inject
    public ExampleResource(final Dependency dependency) {
        this.dependency = Objects.requireNonNull(dependency);
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Example getExample() {
        return this.dependency.giveExample();
    }

}

Dagger 组件可以定义如下:

@Component
public interface Application {

    public ExampleResource exampleEndpoint();
    public XyzResource xyzEndpoint();
    // etc.

}

因此主要方法看起来类似于:

public final class Main {

    public static void main(final String[] args) {
        final Application application = DaggerApplication.create();
        final URI baseUri = UriBuilder.fromUri("http://0.0.0.0/").port(80).build();
        final ResourceConfig resourceConfig = new ResourceConfig();
        // how to initialize `resourceConfig` using `application`?
        final HttpServer httpServer = GrizzlyHttpServerFactory
                .createHttpServer(baseUri, resourceConfig, false);
        try {
            httpServer.start();
        } catch (final IOException ex) {
            ...
        }
    }

}

立即运行应用程序会导致异常:IllegalStateException: InjectionManagerFactory not found.似乎需要该工厂的 Dagger 实现。

我的问题是:如何将 Dagger 与 Jersey 集成?

4

2 回答 2

1

您不应该将其视为“如何将匕首与球衣融为一体”。弄清楚如何设置球衣,然后一旦弄清楚了,就可以担心使用匕首了。

这是(非常粗略地)我会怎么做。

创建您自己的 ResourceConfig 类的实现。

@ApplicationPath("/service")
public class MyResourceConfig extends ResourceConfig {

    @Inject
    public MyResourceConfig(
            @Nonnull final ExampleResource exampleResource) {
        this.register(exampleResource);
    }

}

然后创建一个模块来设置创建 HttpServer 所需的一切

@Module
public class MyServiceModule {

    @Provides
    @Singleton
    @Named("applicationPort")
    public Integer applicationPort() {
        return 80;
    }

    @Provides
    @Singleton
    @Named("applicationBaseUri")
    public URI baseUri(
            @Named("applicationPort") @Nonnull final Integer applicationPort) {
        return UriBuilder.fromUri("http://0.0.0.0/").port(applicationPort).build();
    };

    @Provides
    @Singleton
    public HttpServer httpServer(
            @Named("applicationBaseUri") @Nonnull final URI applicationBaseUri,
            @Nonnull final MyResourceConfig myResourceConfig) {
        return GrizzlyHttpServerFactory
                .createHttpServer(applicationBaseUri, myResourceConfig, false);
    }

}

然后创建公开 HttpServer 的组件。我通常喜欢制作尽可能少暴露的组件。在这种情况下,您只需要公开 HttpServer。

@Singleton
@Component(modules = { MyServiceModule.class })
protected interface ServiceComponent {

    HttpServer httpServer();

    @Component.Builder
    interface Builder {

        // Bind any parameters here...

        ServiceComponent build();

    }

}

然后继续构建您的组件,并启动您的 HttpServer

public static void main(String[] args) {
    final ServiceComponent component = DaggerServiceComponent.builder().build()
    try {
        component.httpServer().start();
    } catch (Exception ex) {
        // handle exception...
    }
}

还有一点需要注意。我个人从不使用 @Named("") 注释。我更喜欢使用限定符。因此,您创建了一个具有唯一值的限定符注释。然后你可以注入类似的东西

@Provides
@Singleton
@MyUniqueQualifier
public String myUniqueQualifierProviderValue() {
    return "something";
}

然后在注入的时候

@Inject
public SomeClass(@MyUniqueQualifier @Nonnull final String myUniqueQualifiedValue) 

如果您使用 @Named 注释,则不会在编译时检查冲突或缺失值。您会在运行时发现未注入值或名称与其他内容冲突。它很快变得混乱。

于 2021-09-28T16:54:30.363 回答
-1

您需要实现一个InjectionManagerFactory返回InjectionManager对 Dagger 的委托,并通过在 中添加一个条目将其注册为服务META-INF/services,类似于此处的 hk2: https ://github.com/jersey/jersey/blob/master/inject/ hk2/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory 但引用您自己的实现。

于 2018-07-13T09:37:25.367 回答