在CDI SessionScoped bean中注入HttpServletRequest

时间:2013-08-12 14:17:27

标签: java java-ee cdi

我有一个会话范围的CDI bean,我需要以某种方式访问​​这个bean的@PostConstruct方法中的HttpServletRequest对象。可能吗?我试图注入这样一个对象,但结果是:

WELD-001408 Unsatisfied dependencies for type [HttpServletRequest] with qualifiers     [@Default] at injection point [[field] @Inject ...]

正如我在Google上所了解的那样,Seam框架具有这样的功能,但我在GlassFish服务器上有一个标准的Java EE应用程序。

是否有可能以某种方式将请求传递给CDI bean的@PostConstruct方法?

2 个答案:

答案 0 :(得分:12)

根据您的评论,您希望访问用户主体。您可以像这样注入:@Inject Principal principal;@Resource Principal principal;,请参阅Java EE 6 Tutorial

<强>更新

我会回答你的直接问题。在Java EE 7(CDI 1.1)中,支持开箱即用的HttpServletRequest注入。但是,在Java EE 6(CDI 1.0)中,不支持开箱即用。要使其正常运行,请将以下课程添加到您的网络应用中:

import javax.enterprise.inject.Produces;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class CDIServletRequestProducingListener implements ServletRequestListener {

    private static ThreadLocal<ServletRequest> SERVLET_REQUESTS = new ThreadLocal<>();

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        SERVLET_REQUESTS.set(sre.getServletRequest());
    }

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        SERVLET_REQUESTS.remove();
    }

    @Produces
    private ServletRequest obtain() {
        return SERVLET_REQUESTS.get();
    }

}

注意:仅在GlassFish 3.1.2.2

上测试

答案 1 :(得分:0)

使用rdcrng中的代码时请注意以下事项:
* producer-method obtain是依赖范围的,因此只对应用程序作用域bean调用一次(并且除了第一个请求之外的每个其他请求将解决问题)
*您可以使用@RequestScoped来解决此问题 *当RequestScoped注释时,您将只获得一个代理,因此您无法将其添加到HttpServletRequest。所以你可能想要一个HttpServletRequest的制作人。

另请注意:根据CDI规范link第3.6段,java ee bean不是托管bean。因此,您将得到两个CDIServletRequestProducingListener实例 - 一个由Java EE容器管理,一个由CDI容器管理。它只能起作用,因为SERVLET_REQUESTS是静态的。

为方便起见,请修改代码。

import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;

@WebListener
public class CDIServletRequestProducingListener implements ServletRequestListener {

private static ThreadLocal<ServletRequest> SERVLET_REQUESTS = new ThreadLocal<ServletRequest>();

@Override
public void requestInitialized(ServletRequestEvent sre) {
    SERVLET_REQUESTS.set(sre.getServletRequest());
}

@Override
public void requestDestroyed(ServletRequestEvent sre) {
    SERVLET_REQUESTS.remove();
}

@RequestScoped
@Produces
private HttpServletRequest obtainHttp() {
    ServletRequest servletRequest = SERVLET_REQUESTS.get();
    if (servletRequest instanceof HttpServletRequest) {
        return (HttpServletRequest) servletRequest;
    } else {
        throw new RuntimeException("There is no HttpServletRequest avaible for injection");
    }
}

}