2013-03-25 54 views
2

我有,我想注入资源和过滤器一个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注释字段在外部类中声明,它被实例化了一次,但是它们被用来在每个请求的基础上注入对象。当我在调试过程中,通过filter步骤,我可以看到,MyFilter.request指向代理包装的com.sun.jersey.server.impl.container.servlet.ThreadLocalInvoker一个实例。

什么是我的自定义供应商(或执行其他)丢失,它需要做定制注入我的过滤器?

请注意,我现在坚持与新泽西1.1.4.1(对不起)。

编辑:使用泽西1.17,我在启动时得到一个异常,而不是:

重度:现场缺少相关性:私人mypackage.MyObject mypackage.MyFilter.myObject

回答

1

我发现使用来自JSR-311Providers可注射接口的解决方法。首先,我不得不让我的供应商实施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被调用时,我用它来查找ContextResolverMyObject和动态检索:

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小费为我送行约Providers。该解决方案有效,但它不是一个漂亮的。我还是想注入MyObject任何地方,只是有它的工作,像HttpServletRequest - 我想知道什么是我的供应商的缺失,它需要做到这一点。

+1

这并没有真正使用Injectable方法。提供者可用作默认注入的一部分,您基本上需要向Jersey服务器注册一个自定义上下文解析器。您可以避免扩展AbstractHttpContextInjectable或实现InjectableProvider并获得相同的结果。 – baradas 2013-07-15 06:47:29

+0

@baradas你是对的,这就是为什么我不喜欢这个解决方案。我没有最终在我的代码中使用它。 – 2013-07-15 15:31:25

+0

@PaulBellora,如果我问,你最终做了什么?我在注入过滤器以及注入提供者方面遇到同样的问题。 – elanh 2015-10-11 12:54:13

1

我碰到这个问题就试图达到同样的目标(即通过注射自定义提供实现提供的东西),发现定制注塑很好地工作,如果你通过一个过滤器工厂的路要走。

因此,不要将@Context MyClass myObj注释放入Filter类中,而是将该类型的注释字段放入负责创建过滤器的过滤器工厂中,并让工厂将“myObj”作为常规参数传递。

我不确定这会有助于你的情况,我还没有调查与每个请求提供程序(我的单身作用域)使用这种影响,所以YMMV。

+0

如果您使用@ResourceFilters(MyFilter.class)注释,如何将参数传递给过滤器类。 – 2017-08-04 14:14:07