我正在将JAX-RS应用程序部署到JBoss EAP 6.2。
我试图从JAX-RS资源类的内部获取一个ServletContext,以便我可以读取在context-param文件中设置的一些WEB-INF/web.xml值。
即,在掌握了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。

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;
    }
}


…最后在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。即RESTEasy某种程度上无法注入ServletContext。请注意,我没有任何其他JAX-RS问题。即如果我对希望通过ServletContext#getInitParameter检索的context-param值进行硬编码,那么将WAR部署到JBoss时,JAX-RS rest功能将按预期工作。

进一步实验发现,只有在对服务方法的参数执行注入时,才会注入ServletContext,如下所示:

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


…但是我不希望更改API。而且,我想一劳永逸地根据context-param值执行一些昂贵的初始化,而不是每次服务方法调用时都要执行。

我的问题是:


为什么注射失败?
我对注释魔术在运行时失败感到有些厌倦,有没有一种方法可以在不使用注释的情况下获取ServletContext
或者,我的MyApplication类是否可以获取ServletContext并将其作为构造函数参数传递给MyResource类?
如果所有其他方法都失败了,我想我总是可以使用Class#getResourceAsStream自己读取和解析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类中,我有以下内容:

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


这作为UserDatabaseResource类工作,这是我的DAL层是单例的,我只需要获取要使用的数据源的JNDI名称(来自web.xml文件)。但是也许这种方法也可以对非单身人士的班级进行一些小的调整。

关于java - @Context未在RESTEasy JAX-RS应用程序中注入(inject)ServletContext,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41990590/

10-10 20:05