首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有构造函数参数的HK2和Impls

带有构造函数参数的HK2和Impls
EN

Stack Overflow用户
提问于 2014-01-21 12:35:24
回答 2查看 2.6K关注 0票数 1

我使用HK2作为泽西RESTful API的一部分。我在多租户系统中工作,在大多数API调用中,承租者是一个path参数。我还有几个DAO,它们目前在构造函数中接受tenantId,例如:

代码语言:javascript
复制
public final class WidgetMapper {
    public WidgetMapper(final int tenantId) { .. }
    ..
}

我想使用HK2为我的应用程序的其他层提供DAO。怎么做才是对的?

  1. 将DAO更改为使用setter而不是构造函数参数。只有..。费克。tenantId是DAO所需状态的一部分。
  2. 添加一层抽象。创建<interface>MapperFactoryMapperFactoryImpl,它有一个无arg构造函数和一组getter,例如getWidgetMappergetGizmoMapper。只有..。这似乎很麻烦。我不想再继续这些额外的课程了。
  3. HK2有什么神奇的方法在运行时将这个int值注入到WidgetMapper构造函数中吗?然后,我可以将tenantId注入映射程序,并将映射器注入到我的其他类中。
  4. ??其他HK2魔法?
EN

回答 2

Stack Overflow用户

发布于 2014-09-23 22:36:09

您需要从请求中的path参数中提取承租者ID,因此只要可以为每个请求实例化DAO,就可以实现一个Factory

代码语言:javascript
复制
public WidgetMapperFactory implements Factory<WidgetMapper> {

    private final ContainerRequestContext containerRequestContext;

    @Inject
    public WidgetMapperFactory(ContainerRequestContext containerRequestContext) {
        this.containerRequestContext = containerRequestContext;
    }

    public WidgetMapper provide() {
        UriInfo uriInfo = containerRequestContext.getUriInfo();
        List<String> matchedUris = uriInfo.getMatchedURIs();
        int tenantId = 1; // Actually work it out from the matched URIs
        return new WidgetMapper(tenantId);
    }

    public void dispose() {
        // Do any clean up you need
    }

}

然后把工厂绑起来:

代码语言:javascript
复制
public MyResourceConfig extends ResourceConfig {

    public MyResourceConfig() {
        register(new AbstractBinder() {
            @Override
            protected void configure() {
                bindFactory(WidgetMapperFactory.class).to(WidgetMapper.class).in(RequestScoped.class);
            }
        });
    }

}

然后您可以将WidgetMapper注入到Resource类中,并且WidgetMapper不知道它在web服务中的使用情况。

票数 4
EN

Stack Overflow用户

发布于 2014-01-21 13:43:50

将DAO更改为使用setter而不是构造函数参数。只有..。费克。tenantId是DAO所需状态的一部分。

如果你的DAO是单身汉,我看不出它是如何工作的(或者至少它是如何干净利落的)。

怎么做才是对的?

IMO,我认为最好的方法是让1)单例DAOs 2)某种类型的代理在DAO被HK2实例化时注入到DAOs中,然后为当前线程提供正确的租户id。

我可以想出两种方法来做到这一点:

选项1:

我还没有尝试过,但我认为您可能可以通过构造函数、私有字段或setter将UriInfo注入DAO。您可以从UriInfo实例中提取当前请求的租户id。

如果我是您,我会为我的DAO创建一个抽象类,将一个UriInfo注入到私有字段中。然后,我将提供一个受保护的方法来从uriInfo.getPathParameters返回当前的租户id

代码语言:javascript
复制
public abstract class AbstractDao {

    // jersey/hk2 provides a proxy that references the current thread-bound request
    @Context
    private UriInfo info;

    protected int getTenantId()
    {
        // always returns the tenant id for the current request.  TODO: add
        // logic to handle calls that don't have a tenant id.
        return Integer.valueOf(info.getPathParameters.getFirst("tenantId");
    }
}

备选方案2:

??其他HK2魔法?

你可以写一个自定义注入解析器

还有一个主意..。

选项3:

这个问题没有直接回答您的问题,因为它没有使用HK2将租户ID注入DAO,但我认为这一点值得一提。

您可以实现自己的ContainerRequestFilter,它获得租户id并将其提供给应用程序中的其他组件。

默认情况下,泽西岛将在筛选器解析资源方法之后,但在实际调用该方法之前调用过滤器。您可以从UriInfo中获得一个ContainerRequestContext,获取租户id路径param,然后将该param填充到您自己的线程局部变量中。然后,您可以在DAO中引用本地线程。同样,我建议在基类中添加一个受保护的方法来封装这个逻辑。

在我的大部分API调用中,承租者是一个path参数。

可以选择使用NameBinding来控制上面描述的行为。

如果您愿意,可以使用常规的ServletFilter来实现选项3。

注:

在我写完这个答案之后,我意识到我认为您可以轻松地扩展ResourceConfig,知道如何获得ServiceLocator的实例,并且您是习惯于添加自己的绑定。如果你不是,让我知道,我会编辑我的答案,以提供更多的细节。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21258312

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档