我希望能够为单个请求按字段注入Datastore,例如:
我看到,你需要将资源注册为单例,就像这样:
@Context
protected HttpServletRequest request;
目前我已经实现了类似于这个方法的方式: 使用属性的Jersey 2.x自定义注入注释 如下所示:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
public @interface TenantDatastore {}
public class TenantDatastoreFactory extends AbstractContainerRequestValueFactory<Datastore> {
public TenantDatastoreFactory() {}
@Override
public Datastore provide() {
ContainerRequest request = getContainerRequest();
return DatastoreManager.getDs(request.getHeaders().get("Host")));
}
@Override
public void dispose(Datastore d) {}
}
public class TenantDatastoreFactoryProvider extends AbstractValueFactoryProvider {
private final TenantDatastoreFactory tenantDatastoreFactory;
@Inject
public TenantDatastoreFactoryProvider(
final MultivaluedParameterExtractorProvider extractorProvider,
ServiceLocator locator,
TenantDatastoreFactory tenantDatastoreFactory) {
super(extractorProvider, locator, Parameter.Source.UNKNOWN);
this.tenantDatastoreFactory = tenantDatastoreFactory;
}
@Override
protected Factory<?> createValueFactory(Parameter parameter) {
Class<?> paramType = parameter.getRawType();
TenantDatastore annotation = parameter.getAnnotation(TenantDatastore.class);
if (annotation != null && paramType.isAssignableFrom(Datastore.class)) {
return tenantDatastoreFactory;
}
return null;
}
}
public class TenantDatastoreInjectionResolver extends ParamInjectionResolver {
public TenantDatastoreInjectionResolver() {
super(TenantDatastoreFactoryProvider.class);
}
}
@Path("/users")
public class User {
@TenantDatastore
private Datastore ds;
private ObjectMapper objectMapper;
public User(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@GET
public Response getUsers(){
return Response.ok(ds.find(User.class).asList()).build();
}
}
在 dropwizard 应用程序的 run 方法中:
environment.jersey().register(new UserResource(objectMapper));
environment.jersey().getResourceConfig().register(new AbstractBinder(){
@Override
public void configure() {
bind(TenantDatastoreFactory.class)
.to(TenantDatastoreFactory.class)
.in(Singleton.class);
bind(TenantDatastoreFactoryProvider.class)
.to(ValueFactoryProvider.class)
.in(Singleton.class);
bind(TenantDatastoreInjectionResolver.class)
.to(new TypeLiteral<InjectionResolver<TenantDatastore>>(){})
.in(Singleton.class);
}
});
我看到,你需要将资源注册为单例,就像这样:
我读到,你必须将资源注册为单例,像这样:
environment.jersey().register(UserResource.class);
但是我必须将对象传递给构造函数,而这在单例模式下是不可能的。javax.servlet.http.HttpServletRequest
和javax.ws.rs.core.Context
与资源实例一起很好地工作,那么我该如何使这种行为对我的用例可行?
TenantDatastoreFactory
绑定到RequestScoped.class
中。 - Paul SamsothabindFactory(TenantDatastoreFactory.class) .proxy(true) .proxyForSameScope(false) .to(Datastore.class) .in(RequestScope.class);
将无法工作。 - sclausen