我有一个POJO,我想注入资源和过滤器:
public final class MyObject { }
我为它实现了一个自定义提供程序:
@Provider
public final class MyProvider
extends AbstractHttpContextInjectable<MyObject>
implements InjectableProvider<Context, Type> {
@Context private HttpServletRequest request;
@Override
public Injectable<MyObject> getInjectable(
ComponentContext componentContext,
Context annotation,
Type type
) {
if (type.equals(MyObject.class)) {
return this;
}
return null;
}
@Override
public ComponentScope getScope() {
return ComponentScope.PerRequest;
}
@Override
public MyObject getValue(HttpContext httpContext) {
//in reality, use session info from injected request to create MyObject
return new MyObject();
}
}
该对象已成功注入我的资源:
@Path("/test")
@ResourceFilters(MyFilter.class)
public final class MyResource {
@Context private HttpServletRequest request;
@Context private MyObject myObject;
@GET
public String execute() {
System.out.println(request != null); //true
System.out.println(myObject != null); //true
return "data";
}
}
但泽西岛未能将其注入我的过滤器:
public final class MyFilter implements ResourceFilter {
@Context private HttpServletRequest request;
@Context private MyObject myObject;
@Override
public ContainerRequestFilter getRequestFilter() {
return new ContainerRequestFilter() {
@Override
public ContainerRequest filter(ContainerRequest containerRequest) {
System.out.println(request != null); //true
System.out.println(myObject != null); //false
return containerRequest;
}
};
}
@Override
public ContainerResponseFilter getResponseFilter() {
return null;
}
}
我猜测差异与以下事实有关:MyFilter中的注入是使用遵循线程局部实例的代理完成的 – 这是因为用@Context注释的字段在外部类中声明,它被实例化一次,但它们用于按请求注入对象.当我在调试期间逐步执行过滤器时,我可以看到MyFilter.request指向包含com.sun.jersey.server.impl.container.servlet.ThreadLocalInvoker实例的代理.
什么是我的自定义提供程序(或其他实现)缺少它需要自定义注入我的过滤器?
请注意,我目前仍然坚持使用Jersey 1.1.4.1(对不起).
编辑:使用Jersey 1.17,我在启动时得到一个例外:
SEVERE: Missing dependency for field: private mypackage.MyObject mypackage.MyFilter.myObject
最佳答案 我找到了使用
JSR-311的
Providers
可注射接口的解决方法.首先,我必须让我的提供者实现
ContextResolver
:
@Provider
public final class MyProvider
extends AbstractHttpContextInjectable<MyObject>
implements InjectableProvider<Context, Type>, ContextResolver<MyObject> {
...
@Override
public MyObject getContext(Class<?> type) {
//in reality, using the same logic as before
return new MyObject();
}
}
然后我将Providers实例注入到我的过滤器中.当调用filter时,我用它来查找MyObject的ContextResolver并动态检索它:
public final class MyFilter implements ResourceFilter {
@Context private HttpServletRequest request;
@Context private Providers providers;
@Override
public ContainerRequestFilter getRequestFilter() {
return new ContainerRequestFilter() {
@Override
public ContainerRequest filter(ContainerRequest containerRequest) {
final ContextResolver<MyObject> myObjectResolver =
providers.getContextResolver(MyObject.class, null);
final MyObject myObject =
myObjectResolver.getContext(MyObject.class);
System.out.println(request != null); //true
System.out.println(myObject != null); //true
return containerRequest;
}
};
}
...
}
信用证转到this answer,因为我对提供商不屑一顾.解决方案有效,但它不是一个漂亮的解决方案.我仍然想在任何地方注入MyObject并让它工作,就像HttpServletRequest一样 – 我想知道我的提供者缺少它需要实现的目的.