@Context对象从哪里来?

14

我已经到处搜索了,但似乎找不到清晰的答案...

服务器(我的问题是glassfish)注入带有@Context注释的实际对象的机制是什么?更具体地说,如果我想编写一个类来执行以下操作:

@Path("/")
public class MyResource {
  @GET
  public String doSomething(@Context MyObject obj) {
    // ...
  }
}
那么我该怎么做呢?MyObject在哪里被实例化,由谁负责实例化,以及如何实例化?
编辑:我看到过类似以下内容的东西: 在JAX-RS中使用@Context、@Provider和ContextResolver http://jersey.576304.n2.nabble.com/ContextResolver-confusion-td5654154.html 但是这与我之前看到的不符,例如在org.neo4j.server.rest.web.RestfulGraphDatabase的构造函数中,它具有以下签名:
public RestfulGraphDatabase(
  @Context UriInfo uriInfo,
  @Context Database database,
  @Context InputFormat input,
  @Context OutputFormat output,
  @Context LeaseManager leaseManager )
4个回答

8
你可以编写自己的注入提供程序并将其插入Jersey中 - 查看SingletonTypeInjectableProviderPerRequestTypeInjectableProvider - 扩展其中一个类(取决于您想要为注入对象设置的生命周期),并在Web应用程序中注册您的实现作为提供程序。
例如,像这样:
@Provider
public class MyObjectProvider extends SingletonTypeInjectableProvider<Context, MyObject> {
    public MyObjectProvider() {
        // binds MyObject.class to a single MyObject instance
        // i.e. the instance of MyObject created bellow will be injected if you use
        // @Context MyObject myObject
        super(MyObject.class, new MyObject());
    }
}

要在您的Web应用程序中包含提供者,您有几个选项:

  1. 如果您的应用程序使用类路径扫描(或包扫描),请确保提供程序位于正确的包/类路径中
  2. 或者,您可以使用META-INF / services条目进行简单的注册(添加META-INF / services / com.sun.jersey.spi.inject.InjectableProvider文件,并在其内容中添加提供程序类的名称)

如果您正在对javax.ws.rs.core.Application进行子类化,则可以在Application的构造函数中使用this.getSingletons().add(new MyObjectProvider());将提供程序注册。 - justin
链接已经失效。 - David Berg
请尝试使用以下链接:https://jersey.java.net/nonav/apidocs/1.19/jersey/com/sun/jersey/spi/inject/SingletonTypeInjectableProvider.htmlhttps://jersey.java.net/nonav/apidocs/1.19/jersey/com/sun/jersey/spi/inject/PerRequestTypeInjectableProvider.html - elanh
1
类已从2.0+版本中移除。 - elanh

3
我觉得我可能有所发现……如果这个方法可行,那么马丁应该会得到部分功劳。 :)
看起来@Provider类必须实现com.sun.jersey.spi.inject.Injectable接口。然而,我不确定这是否足以使@Context被注入。缺少的是,我们必须告诉Web应用程序的ResourceConfig对象有关@Provider的信息。在我尝试做的事情的背景下,并从neo4j-server中获取提示,剩余的工作归结为:
扩展com.sun.jersey.spi.container.servlet.ServletContainer,并覆盖configure方法:
@Override
protected void configure(WebConfig wc, ResourceConfig rc, WebApplication wa)
{
  super.configure( wc, rc, wa );
  Set<Object> singletons = rc.getSingletons();
  singletons.add(new MyObjectProvider());
}
  • 在web.xml部署描述文件中指定此容器必须使用:
<servlet>
  <servlet-name>JAX-RS Servlet Container</servlet-name>
  <servlet-class>com.blah.MyServletContainer</servlet-class>
</servlet>

1
哦,不用了 - 你不需要这样做。我已经编辑了我的答案,展示如何注册你的提供者。 - Martin Matula

0

我认为您不能像MyObject这样使用@Context与用户定义的类型。它是用于注入jax-ws已经理解的类型的。在这里提到here

JAX-RS规范的第5章介绍了所有可与@Context一起使用的标准JAX-RS Java类型。

您可能想要使用@FormParam@PathParam之类的东西。请参阅规范的第2.3节以获取说明。以下是您的答案,从规范的该部分复制而来:

通常情况下,Java方法参数的类型可能是以下之一:
  1. 原始类型;
  2. 具有接受单个字符串参数的构造函数;
  3. 具有名为valueOf或fromString的静态方法,该方法接受单个字符串参数(例如,Integer.valueOf(String)和java.util.UUID.fromString(String));或者
  4. 是List、Set或SortedSet,其中T满足上述2或3。生成的集合是只读的。

正确。您只能注入此处列出的12个允许的对象实例:https://readlearncode.com/java-ee/what-is-javax-ws-rs-core-context-httpheaders-and-uriinfo/ - Alex Theedom

-1

这些文档是否说明了如何自己编写这样的功能?我理解这就是问题所在。 - Ludwig Magnusson
你不需要这样做。这是为框架组件设计的。如果你想要依赖注入,可以寻找一个 DI 容器,比如 Spring。 - Ryan Stewart
链接回答不是被看作不好的吗?因为链接的网站内容可能会发生变化。 - smcg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接