我正在尝试编写一个CDI扩展,需要通过<context-param>
访问web.xml中定义的上下文参数。我认为有两种方法可以做到这一点:
ServletContext
并致电getInitParameter()
web.xml
不幸的是,我需要两个解决方案的ServletContext
,并且似乎不可能。这里的问题是一些容器在创建ServletContext
之前启动CDI。即使在CDI启动之前ServletContext
可用,也似乎无法从CDI扩展中访问它。我尝试使用ServletContextListener
将ServletContext
存储在静态ThreadLocal
中。这似乎工作正常,但它会造成内存泄漏,因为我无法可靠地清理ThreadLocal
。
在你回答之前还有两条评论:
谢谢! :)
答案 0 :(得分:4)
我试图通过在JBoss 7.1上与CDI bean共享上下文来做类似的事情。虽然它对我不起作用,但我不确定JBoss7.1的当前状态是否会导致问题,所以它可能对你有用吗?
我所做的是在启动时有一些东西可以访问ServletContext
(在我的例子中是一个JAX-RS Application
,但可能是一个监听器或servlet)访问一个应用程序范围的bean并在其中设置ServletContext
。
为了桥接到CDI的世界,我使用以下URI中的配方来创建bean实例: http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html/extend.html#d0e4978
相关代码如下:
@SuppressWarnings("unchecked")
public <T> T getBean(Class<T> instanceClass) throws NamingException
{
BeanManager beanManager
= (BeanManager) InitialContext.doLookup("java:comp/BeanManager");
AnnotatedType<Object> annotatedType
= (AnnotatedType<Object>) beanManager.createAnnotatedType(instanceClass);
InjectionTarget<Object> injectionTarget
= beanManager.createInjectionTarget(annotatedType);
CreationalContext<Object> context
= beanManager.createCreationalContext(null);
Object instance = injectionTarget.produce(context);
injectionTarget.inject(instance, context);
injectionTarget.postConstruct(instance);
return (T) instance;
}
然后您可以将其设置为看起来像这样的bean:
package some.package;
import javax.enterprise.context.ApplicationScoped;
import javax.servlet.ServletContext;
/** An application context, initialised on application startup. */
@ApplicationScoped
public class AppContext
{
private ServletContext servletContext;
/** Return the servlet context for the current application. */
public ServletContext getServletContext()
{
return servletContext;
}
public void setServletContext(ServletContext servletContext)
{
this.servletContext = servletContext;
}
}
使用如下代码段:
getBean(AppContext.class).setServletContext(servletContext);
在您的启动代码中。然后,您应该能够@Inject
在您想要的任何CDI构造中的上下文... 假设它在您的servlet init之后运行或者其他任何内容。
例如:
@Inject
private AppContext appContext;
如果这在其他情况下有效,我会很好奇......
答案 1 :(得分:0)
不确定您正在使用哪个容器,但在JBoss中看起来至少可以使用注释inject the ServletContext。这不适合你,还是我没有正确理解你的CDI扩展的性质?
编辑:啊。我从未使用过CDI实现,但是可以创建一个ServletContextListener
来生成一个CDI事件,其中ServletContext
作为事件属性之一。然后,您可以在扩展程序中监听事件并提取ServletContext
。
答案 2 :(得分:0)
正如你已经注意到自己和Femi所评论的,如果ServletContext不可用,你就无法从中得到任何东西(比如init params)。 读取web.xml文件是可能的,但是肯定它很疯狂并且不可移植,但是你总是可以尝试在你的特定部署上执行它,你可以从WEB-INF here <获取一个读取smth的例子/ p>