5

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

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

正如我在谷歌搜索时了解到的,Seam 框架具有这样的功能,但我在 GlassFish 服务器上有一个标准的 Java EE 应用程序。

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

4

2 回答 2

12

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

更新

我会回答你的直接问题。在 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 上测试

于 2013-08-12T16:37:36.730 回答
0

使用 rdcrng 中的代码时,请注意以下几点:
* producer-methodobtain是依赖范围的,因此仅对应用程序范围的 bean 调用一次(并且将解决除第一个请求之外的所有其他请求的问题)
* 您可以解决这个问题with @RequestScoped
* 当 RequestScoped 注解时,你只会得到一个代理,因此你不能将它转换为 HttpServletRequest。所以你可能想要一个 HttpServletRequest 的生产者。

另请注意:根据 CDI 规范链接段落 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");
    }
}

}

于 2016-07-04T08:03:45.130 回答