【问题标题】:Is it thread unsafe for a @SessionScoped bean to maintain a reference to its HttpSession?@SessionScoped bean 维护对其 HttpSession 的引用是否线程不安全?
【发布时间】:2013-01-08 16:11:21
【问题描述】:

看看the unrelated portion of this answer to another question,虽然我理解为什么在问题示例中对请求和响应的引用是线程不安全的,为什么 SessionScoped bean 引用它所绑定的 HttpSession 是线程不安全的?

@SessionScoped
public class SessionManager {
    HttpSession session = null;
    ...
    @PostConstruct void initialize() {
        this.session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false);
    }

    private void onLogin(@Observes @LoggedIn User user) {

        // (1) housekeeping stuff

        // (2) destroy older, duplicate login session, if user did not previously 
        //     logout, in which case it would be really handy to have a reference
        //     to HttpSession. 

    }
}

【问题讨论】:

    标签: jsf-2 cdi httpsession


    【解决方案1】:

    在实现我在上面勾勒出的示例时(请参阅 OP),我意识到维护对会话的引用并不好,因为它确实是线程不安全的。这是臭代码。

    我惊讶地发现不仅旧会话无效,而且当前会话也被容器破坏了!因此,用户在两个浏览器中都已注销。后来,我遇到了this Websphere best practices documentation,虽然我没有使用 Websphere,但它帮助我意识到缓存会话根本不是一个好习惯:

    避免尝试在每个 servlet 或 JSP 文件之外保存和重用 HttpSession 对象。

    HttpSession对象是HttpRequest的一个函数(只能通过req.getSession方法获取),它的副本只在servlet或JSP文件的service方法的生命周期内有效。您不能缓存 HttpSession 对象并在 servlet 或 JSP 文件范围之外引用它。

    不需要缓存HttpSession;可以改为缓存会话 ID,当发现重复会话时,只需将前一个重复会话的 ID 添加到 Set<String> invalidatedLoginSessionIds. 然后重构应用程序,以便在收到来自旧会话的请求后立即使旧会话无效并将旧浏览器重定向到适当的面。如果没有收到这样的请求,旧会话将简单地超时并被销毁,所以不用担心。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-26
      • 2013-09-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多