java - 使用CDI登录,@Produces返回缓存值

标签 java jsf scope cdi lifecycle

我正在尝试使用 CDI @javax.enterprise.context.SessionScoped

实现登录机制

代码:

@Named
@SessionScoped
public class Auth implements Serializable {

  private User user;

  @Inject
  private UserStore userStore;

  @Produces @CurrentUser
  public User getUser() {
    if (user == null) {
        Principal principal= FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();

            if (principal != null) {

                Map parameters = new HashMap();
                parameters.put("email", principal.getName());

                user = (User) userStore.findWithNamedQuery(User.GET_BY_EMAIL, parameters).get(0);
            }
        }

        return user;
    }

    public void logout() throws IOException {
        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
        ec.invalidateSession();
        ec.redirect(ec.getRequestContextPath() + "/");
    }
}

始终接收相同User实例的类:

@Stateful
public class NewsService implements Serializable {

    @Inject @CurrentUser
    private User currentUser;

    @Inject
    private NewsStore newsStore;

    public List<News> getNewsForLoggedUser(Integer start, Integer limit) {
        Map<String, Object> params = new HashMap<>();
        params.put("user", currentUser);

        return (List<News>) newsStore.findWithNamedQuery(News.getAllForUser, params, start, limit);
    }
}

问题出在 getUser() 方法上。即使 session 已失效,它仍然会返回第一次登录时的值。如何销毁 CDI bean 或更改它以便它始终输出实际值?我尝试使用 @PreDestroy 注释 logout() 方法,但它产生了这样的错误:

13:20:50,329 ERROR [org.jboss.weld.Bean] (default task-22) WELD-000019 Error destroying an instance Managed Bean [class com.intenso.presentation.Auth] with qualifiers [@Default @Any @Named] of com.intenso.presentation.Auth@59821e

我正在 WildFly 8.0.0.Alpha4 上运行

最佳答案

问题可能来自这样一个事实:您的生产者没有显式作用域,因此它具有@Dependent伪作用域。这意味着生产者代码在您的 EJB 构建时被调用一次,并且 Injected 值在您的 EJB 生命周期中保持不变。

您没有提到您的 @Stateful EJB 是如何使用的,但我假设它被注入(inject)到另一段代码中,因此您的代码保持它比请求更长的时间。

要纠正您的错误,您应该为生产者提供正常范围(@RequestScoped似乎是最佳选择)。所以你的生产者代码将变成

@Produces @CurrentUser @RequestScoped
public User getUser() { ... }

请记住,生产者不会从包含它的 bean 继承作用域。 在这个正常范围内,user bean 不会被直接注入(inject),但 CDI 将注入(inject)它的代理。因此,currentUser 仅在当前请求的生命周期内保持不变。

请立即阅读 dependent scope chapter of the CDI 1.1 spec ,很有帮助

关于java - 使用CDI登录,@Produces返回缓存值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19294532/

相关文章:

java - 当集合为空时省略 JAXB 中的包装器标记

java - HttpsCookieFilter - IllegalStateException : getOutputStream() has already been called for this response

jsf - p :autoComplete - Pass More parameters

jsf - 如何切换 p :tab in the same form using a command button

javascript - javaScript 中的警报函数

python 作用域 - 子作用域应该有权访问父作用域?

java - 在struts1中上传文件

java - 当 10Mb 空闲时,Android 分配 4Mb 时出现 OutOfMemoryError

maven - 将基于 Maven 的 JSF 项目部署到 Tomcat 导致 java.lang.ClassNotFoundException : javax. faces.webapp.FacesServlet

javascript - 对循环头中的 block 作用域和 Javascript 中的参数感到困惑