我使用HK2作为泽西RESTful API的一部分。我在多租户系统中工作,在大多数API调用中,承租者是一个path参数。我还有几个DAO,它们目前在构造函数中接受tenantId,例如:
public final class WidgetMapper {
public WidgetMapper(final int tenantId) { .. }
..
}我想使用HK2为我的应用程序的其他层提供DAO。怎么做才是对的?
tenantId是DAO所需状态的一部分。<interface>MapperFactory和MapperFactoryImpl,它有一个无arg构造函数和一组getter,例如getWidgetMapper和getGizmoMapper。只有..。这似乎很麻烦。我不想再继续这些额外的课程了。发布于 2014-09-23 22:36:09
您需要从请求中的path参数中提取承租者ID,因此只要可以为每个请求实例化DAO,就可以实现一个Factory。
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
}
}然后把工厂绑起来:
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服务中的使用情况。
发布于 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
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的实例,并且您是习惯于添加自己的绑定。如果你不是,让我知道,我会编辑我的答案,以提供更多的细节。
https://stackoverflow.com/questions/21258312
复制相似问题