@Context 不在 RESTEasy JAX-RS 应用程序中注入 ServletContext

@Context not injecting ServletContext in RESTEasy JAX-RS application

我正在将 JAX-RS 应用程序部署到 JBoss EAP 6.2。 我正在尝试从 JAX-RS 资源 class 内部获取 ServletContext,以便我可以读取我在 WEB-INF/web.xml 文件中设置的一些 context-param 值。 也就是说,在我掌握 ServletContext 之后,我打算调用 ServletContext#getInitParam 来获取值。 我正在按照建议 here.

使用注入来获取 ServletContext

我的 web.xml 的相关部分是:

<servlet>
    <servlet-name>resteasy-servlet</servlet-name>
    <servlet-class>
        org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
    </servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>foo.MyApplication</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>resteasy-servlet</servlet-name>
    <url-pattern>/jax-rs/*</url-pattern>
</servlet-mapping>

所以我正在使用与 JBoss 捆绑在一起的 RESTEasy。

Class MyApplication 是:

public class MyApplication extends Application {

    private Set<Object> singletons = new HashSet<>();

    public MyApplication() {
        singletons.add( new MyResource() );
    }

    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }
}

... 最后在 class MyResource 我有以下内容:

@Path(...)
public class MyResource {

    @Context
    ServletContext context;

    public MyResource() {
        // I understand context is supposed to be null here
    }

    // ... but it should have been injected by the time we reach the service method.
    @Path("/somePath")
    @GET
    @Produces(MediaType.APPLICATION_JSON) 
    public Response someMethod( ) {
        if (context==null) throw new RuntimeException();
        ...
    }
}

上面的代码总是导致 RuntimeException 被抛出。 IE。 RESTEasy 以某种方式无法注入 ServletContext。请注意,我没有任何其他 JAX-RS 问题。 IE。如果我硬编码我希望能够通过“ServletContext#getInitParameter”检索的 context-param 值,那么当 WAR 部署到 JBoss 时,JAX-RS 剩余功能将按预期工作.

进一步试验我发现 ServletContext 只有在我像这样在服务方法的参数上执行注入时才会被注入:

@Path("/somePath")
@GET
@Produces(MediaType.APPLICATION_JSON) 
public Response someMethod(@Context ServletContext servletContext) {
    ...
}

... 但是我不想更改 API。此外,我想一劳永逸地基于 context-param 值执行一些昂贵的初始化,而不是在每次服务方法调用时都执行。

我的问题是:

  1. 为什么注入失败?
  2. 我对运行时失败的注解魔术有点厌倦了,有没有办法在不使用注解的情况下获得 ServletContext
  3. 或者,我的 MyApplication class 是否可以获取 ServletContext 并将其作为构造函数参数传递给 MyResource class?
  4. 如果一切都失败了,我想我总是可以使用 Class#getResourceAsStream ?
  5. 自己读取和解析 web.xml 文件

根据链接到 this answer 的 FrAn 的评论,这就是我最终做的事情:

public class JaxRsApplication extends Application {

    private Set<Object> singletons = new HashSet<>();

    public JaxRsApplication(@Context ServletContext servletContext) {
        Assert.assertNotNull(servletContext);
        singletons.add( new UserDatabaseResource(servletContext) );
    }

    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }
}

... 然后,在 UserDatabaseResource class 我有以下内容:

public UserDatabaseResource(ServletContext servletContext) {
    Assert.assertNotNull(servletContext);
    ...
    String jndiNameForDatasource = servletContext.getInitParameter("whatever")) ;
    ...
}

这是因为 UserDatabaseResource class 这是我的 DAL 层是一个单例,我只需要获取要使用的数据源的 JNDI 名称(来自 web.xml 文件).但也许这种方法也适用于非单例 classes 的一些小调整。