@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
值执行一些昂贵的初始化,而不是在每次服务方法调用时都执行。
我的问题是:
- 为什么注入失败?
- 我对运行时失败的注解魔术有点厌倦了,有没有办法在不使用注解的情况下获得
ServletContext
?
- 或者,我的
MyApplication
class 是否可以获取 ServletContext
并将其作为构造函数参数传递给 MyResource
class?
- 如果一切都失败了,我想我总是可以使用
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
class 我有以下内容:
public UserDatabaseResource(ServletContext servletContext) {
Assert.assertNotNull(servletContext);
...
String jndiNameForDatasource = servletContext.getInitParameter("whatever")) ;
...
}
这是因为 UserDatabaseResource
class 这是我的 DAL 层是一个单例,我只需要获取要使用的数据源的 JNDI 名称(来自 web.xml
文件).但也许这种方法也适用于非单例 classes 的一些小调整。
我正在将 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
值执行一些昂贵的初始化,而不是在每次服务方法调用时都执行。
我的问题是:
- 为什么注入失败?
- 我对运行时失败的注解魔术有点厌倦了,有没有办法在不使用注解的情况下获得
ServletContext
? - 或者,我的
MyApplication
class 是否可以获取ServletContext
并将其作为构造函数参数传递给MyResource
class? - 如果一切都失败了,我想我总是可以使用
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
class 我有以下内容:
public UserDatabaseResource(ServletContext servletContext) {
Assert.assertNotNull(servletContext);
...
String jndiNameForDatasource = servletContext.getInitParameter("whatever")) ;
...
}
这是因为 UserDatabaseResource
class 这是我的 DAL 层是一个单例,我只需要获取要使用的数据源的 JNDI 名称(来自 web.xml
文件).但也许这种方法也适用于非单例 classes 的一些小调整。