gpt4 book ai didi

java - 从 session 监听器访问和修改应用程序范围的托管 Bean 的属性

转载 作者:行者123 更新时间:2023-12-02 00:22:55 24 4
gpt4 key购买 nike

我需要访问应用程序范围的托管 bean 来修改 HttpSessionListener 中的某些属性。

我已经使用过如下内容:

@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
User user = userService.findBySessionId(session.getId());

ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();

ApplicationScopedBean appBean = (ApplicationScopedBean) externalContext.getApplicationMap().get("appBean");

appBean.getConnectedUsers().remove(user);
}

externalContext = FacesContext.getCurrentInstance().getExternalContext() 已经在此处导致了空指针异常,即使没有,我也不确定是否可以通过上述方式访问 appBean。

有什么想法吗?

最佳答案

FacesContext 仅在服务于调用了 FacesServlet 的 Web 浏览器发起的 HTTP 请求的线程中可用。在 session 销毁期间,不一定有 HTTP 请求的方式。 session 通常由容器管理的后台线程销毁。这不会通过 FacesServlet 调用 HTTP 请求。因此,您不应期望 FacesContext 在 session 销毁期间始终存在。仅当您在 JSF 托管 bean 内调用 session.invalidate() 时,FacesContext 才可用。

如果您的应用程序范围托管 Bean 由 JSF @ManagedBean 管理,那么很高兴知道 JSF 将其作为 ServletContext 的属性存储在幕后。 ServletContext 反过来可通过 HttpSession#getServletContext() 在 session 监听器中使用。 .

所以,应该这样做:

@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
User user = userService.findBySessionId(session.getId());
ApplicationScopedBean appBean = (ApplicationScopedBean) session.getServletContext().getAttribute("appBean");
appBean.getConnectedUsers().remove(user);
}

如果您正在运行支持 Servlet 3.0 的容器,另一种方法是让您的应用程序作用域 bean 实现 HttpSessionListener 并在构造时将其自身注册为此类。这样您就可以直接引用 connectedUsers 属性。

@ManagedBean
@ApplicationScoped
public class AppBean implements HttpSessionListener {

public AppBean() {
ServletContext context = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
context.addListener(this);
}

@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
User user = userService.findBySessionId(session.getId());
connectedUsers.remove(user);
}

// ...
}

另一种选择是将User保留在 session 范围内作为 session 范围的托管bean。然后,您可以使用 @PreDestroy 注解来标记 session 被销毁时应调用的方法。

@ManagedBean
@SessionScoped
public class User {

@ManagedProperty("#{appBean}")
private AppBean appBean;

@PreDestroy
public void destroy() {
appBean.getConnectedUsers().remove(this);
}

// ...
}

这样做的另一个好处是,User 在 EL 上下文中可用作 #{user}

关于java - 从 session 监听器访问和修改应用程序范围的托管 Bean 的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10603357/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com