本文介绍了从会话侦听器访问和修改Application-Scoped Managed Bean的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to access an application-scoped managed bean to modify certain properties from within an HttpSessionListener.

我已经使用过如下内容:

I already used something like the following:

@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是否可以通过上述方式访问。

externalContext = FacesContext.getCurrentInstance().getExternalContext() causes a null pointer exception here already, and even if it didn't I'm not sure appBean could be accessible the above way.

任何想法?

推荐答案

FacesContext 仅在服务于webbrowser发起的HTTP请求的线程中可用,该请求已调用 FacesServlet的。在会话销毁期间,不一定是HTTP请求的手段。会话通常由容器管理的后台线程销毁。这不会通过 FacesServlet 调用HTTP请求。因此,在会话销毁期间,您不应期望 FacesContext 始终存在。只有在JSF托管bean中调用 session.invalidate()时,才能使用 FacesContext

The FacesContext is only available in the thread serving the HTTP request initiated by the webbrowser which has invoked the FacesServlet. During a session destroy there's not necessarily means of a HTTP request. Sessions are usually destroyed by a background thread managed by the container. This does not invoke a HTTP request through the FacesServlet. So you should not expect the FacesContext to be always there during the session destroy. Only when you call session.invalidate() inside a JSF managed bean, then the FacesContext is available.

如果您的应用程序作用域托管bean由JSF @ManagedBean 管理,那么很高兴知道JSF将它存储在封面下作为 ServletContext 的属性。 <$ href =http://docs.oracle.com/javaee/6/api/javax/servlet/http在会话监听器中提供 ServletContext /HttpSession.html#getServletContext%28%29\"rel =nofollow> HttpSession#getServletContext()

If your application scoped managed bean is managed by JSF @ManagedBean, then it's good to know that JSF stores it under the covers as an attribute of the ServletContext. The ServletContext in turn is available in the session listener by HttpSession#getServletContext().

所以,这应该做:

@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 属性。

If you're running a Servlet 3.0 capable container, an alternative is to just let your application scoped bean implement HttpSessionListener and register itself as such upon construction. This way you have direct reference to the connectedUsers property.

@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 保留为会话范围的托管bean。然后,您可以使用 @PreDestroy 注释来标记在销毁会话时应该调用的方法。

Again another alternative is to keep the User in the session scope as a session scoped managed bean. You can then use the @PreDestroy annotation to mark a method which should be invoked when the session is destroyed.

@ManagedBean
@SessionScoped
public class User {

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

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

    // ...
}

这具有额外的好处,用户在EL上下文中可用#{user}

This has the additional benefit that the User is in EL context available as #{user}.

这篇关于从会话侦听器访问和修改Application-Scoped Managed Bean的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 20:23