jakarta-ee - 从 CDI 扩展访问 servlet 上下文参数

标签 jakarta-ee servlets cdi

我正在尝试编写一个 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/

相关文章:

java - 在 JSF2 中通过 AJAX 加载页面内容

java - 如何在hibernate中映射java属性

css - 在jsp中一次又一次地重新加载头文件

java - 来自 servlet 的静态方法

java - 如何将 CDI @ApplicationScoped bean @Inject 到 @RequestScoped JAX-RS bean 中?

jakarta-ee - 是否可以将 CDI Bean 注入(inject) Java EE 6 中的静态变量?

java - 如何用java制作数据库监听器?

google-chrome - 在 Apache Tomcat 中部署的 Webapp 登录失败

java - 是否可以让 JAX-RS 服务处理同一 URI 上的 GET 并让 WebServlet 处理 POST?

glassfish - "Unable to convert ejbRef for ejb"在将 @Stateless EJB 的 CDI (Weld) 注入(inject) Glassfish 中的 @SessionScoped JSF2 bean 上