我正在尝试编写一个 CDI 扩展,它需要通过 <context-param>
访问 web.xml 中定义的上下文参数。 。我认为有两种方法可以做到这一点:
- 以某种方式获取
ServletContext
并调用getInitParameter()
- 手动解析
web.xml
不幸的是我需要 ServletContext
对于这两种解决方案并获得它似乎是不可能的。这里的问题是一些容器在ServletContext
之前启动CDI。被 build 。即使 ServletContext
在 CDI 启动之前就可用,但似乎无法从 CDI 扩展访问它。我尝试了 ServletContextListener
存储 ServletContext
在静态ThreadLocal
。这似乎工作正常,但它会造成内存泄漏,因为我无法清理 ThreadLocal
可靠。
在回答之前还有两条评论:
- 使用其他方法来读取配置参数(例如使用 JNDI)对我来说不是一个选择,因为我正在尝试编写一个 CDI 扩展来与第 3 方框架集成。
- 我知道,对于这个问题,可能没有任何解决方案可以在环境/容器之间 100% 可移植。但如果我找到一个适用于大多数情况的解决方案,我会很高兴。
谢谢! :)
最佳答案
我尝试在 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);
在你的启动代码中。然后,您应该能够在您想要的任何 CDI 构造中 @Inject
上下文...假设它是在您的 servlet init 或其他什么之后运行的。
例如:
@Inject
private AppContext appContext;
我很好奇这是否适用于其他情况......
关于jakarta-ee - 从 CDI 扩展访问 servlet 上下文参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7200507/