在Servlet中使用CDI注入

Jon*_*han 10 servlets code-injection cdi servlet-filters

我试图@Inject@SessionScoped豆成过滤器

@WebFilter("/*")
public class IdentityFilter implements Filter, Serializable {

    @Inject
    private LoginUser loginUser;
...
Run Code Online (Sandbox Code Playgroud)

这里LoginUser@SessionScoped

目的是loginUser表示会话的登录用户.

问题是看起来我并不总是loginUser从当前会话中获取,因为一个会话的LoginUser对象正在与另一个会话共享,所以会话之间会出现"泄漏".显然这不好.

我想知道这是因为Filter对象是单例,还是至少在容器(glassfish)的请求和会话之间重用.(对?)

是否有更好的方法来获取LoginUser当前会话的对象而不使用Filter上的属性?

Jon*_*han 9

我的问题是容器中只有一个Filter实例,实际上是一个单例.似乎CDI在第一次使用时将第一个会话级对象注入Filter,然后Filter会永久存储该引用,即使对于其他会话也是如此.

我找到了这个解决方案,注入一个工厂对象(Instance),每次Filter运行时我都可以使用它来获取会话实例,即

 @WebFilter("/*")
 public class IdentityFilter implements Filter, Serializable {

      @Inject 
      private Instance<LoginUser> loginUserSource;
Run Code Online (Sandbox Code Playgroud)

并在

 @Override
 public void doFilter(...)
      LoginUser login   = loginUserSource.get();
Run Code Online (Sandbox Code Playgroud)

这似乎解决了我的问题.

谢谢

  • 实际上,CDI使用代理工作,而不是实际注入的LoginUser实例,只要它没有Dependent范围并满足我的第一个注释的要求. (5认同)
  • +1到Fabricio Lemos的回答.CDI提供代理.这是CDI规范(适用于所有NormalScoped bean)的强制要求.请确保您使用的@SessionScoped确实是CDI(javax.enterprise.context.SessionScoped)而不是JSF(java.faces.bean.SessionScoped)中的那个.如果您的IDE只是从错误的包中自动导入注释,这是一个常见的错误.从EE6开始,这些JSF Scopes被认为是遗留的,甚至可能在未来的JSF版本中被弃用. (2认同)