3

我想为企业 Java 系统(JSP、Servlet、EJB)开发一个可以以静态方式(静态方法)使用的实用程序类。它包含一些能够访问HttpSession用户对象并检索一些已经存储为属性的有用信息(例如当前用户ID)的方法。

你们中的一些人可能想知道为什么我需要这样的东西,而我可以简单地将HttpSession对象传递到任何地方。实际上,我正在开发一个遗留的 Java EE 5.0 系统,并且一些实用程序类(不是 Servlet、JSP 或 EJB)无法访问该HttpSession对象。

是否可以实现这样的实用程序类?我/你应该在这里考虑一些限制:

  • servlet/JSP 托管在与托管 EJB 不同的机器上。
  • 系统在 Weblogic 10.3.0 上运行。
  • 在 weblogic 上,有许多服务器(托管 servlet/JSP)并且它们在同一个集群下。EJB 服务器也是如此。
  • 如果我在实用程序类中声明一些静态Collection,它会起作用吗?或者由于多个类加载器和多个 JVM 可能会有不止一个副本?
  • 也许我应该使用共享文件或共享数据库来实现它?我什至怎么能跟踪哪个用户调用了实用程序类?也许跟踪线程?或者可能与交易有关的东西?
4

2 回答 2

5

利用ThreadLocal. 您不应该HttpSession直接将其存储在那里。javax.servlet服务层不应该对API有任何依赖。相反,从直接提取所需信息HttpSession并将其存储在那里。

例如,当您想将User的属性公开HttpSession为线程局部变量时:

public class SomeContext {

    private static ThreadLocal<SomeContext> instance = new ThreadLocal<SomeContext>();
    private User user;

    private SomeContext(User user) {
        this.user = user;
    }

    public static SomeContext getCurrentInstance() {
        return instance.get();
    }

    public static SomeContext newInstance(User user) {
        SomeContext someContext = new SomeContext(user);
        instance.set(someContext);
        return someContext;
    }

    public void release() {
        instance.remove();
    }

    public User getUser() {
        return user;
    }

}

这在doFilter()一个servlet 过滤器中:

User user = (User) request.getSession().getAttribute("user");
SomeContext someContext = SomeContext.newInstance(user);

try {
    chain.doFilter(request, response);
} finally {
    // It's very important to do this in finally!
    // Threads are namely pooled by the container.
    someContext.release();
}

在特定过滤器之后在同一线程中运行的任何代码中,包括 EJB,您可以获得User如下内容:

User user = SomeContext.getCurrentInstance().getUser();
// ...
于 2013-03-19T14:11:53.300 回答
1

HttpSession 是线程本地的。

你真的需要一个 HttpSession 还是你可以用一个静态的 ThreadLocal 属性做你想做的事?

请参阅:http ://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html

顺便说一句,Apache Shiro 使用这个类来存储一些“会话”信息。

于 2013-03-19T13:58:47.383 回答