7

我在 GlassFish 上运行 RESTful java 后端。附加到它的是一个 HTML5 / JS 前端,我可以将它放入 webapp 项目中(然后将后端作为依赖项包含在内),或者在不同位置的 IIS 网络服务器上运行。CORS 不是问题。无论解决以下问题:

情况:

  1. User1 登录并且数据库路径设置为“db/user1/”
  2. User1 将“值 1”插入数据库
  3. User2 登录并且数据库路径设置为“db/user2/”
  4. User1 尝试从数据库中删除“值 1”

User1 将无法从 db/user1 中删除值 1,因为数据库路径已更改为 db/user2,并且该数据库中没有值 1。

public class DataAccess{
    private static DataAccess dataaccess;
    private String databasepath;

    public static DataAccess getInstance() {
        if (dataaccess == null) {
            dataaccess = new DataAccess();
        }
    }
}

如何修改 getInstance() 方法以使其充当单例,但仅在该用户的线程内?我看到了一个叫做threadlocal的东西,但没有完全理解,这可能是一个解决方案吗?

任何帮助都是肯定的。

4

2 回答 2

10

可以ThreadLocal在工厂模式中使用该类:

public class DataAccess{
    private static ThreadLocal<DataAccess> THREAD_LOCAL = new ThreadLocal() {
     @Override
     protected DataAccess initialValue() {
             return new DataAccess();
     }
    };
    private String databasepath;

    public static DataAccess getInstance() {
      return THREAD_LOCAL.get();
    }
}

但是,这将导致内存泄漏。因此,您需要使用Servlet 过滤器在请求开始时设置值,然后在结束时将其删除,例如:

   public void doFilter(ServletRequest request,
      ServletResponse response, FilterChain chain) 
      throws IOException, ServletException {
      DataAccess.set(new DataAccess("SomeValue"));
      try {
        chain.doFilter(request, response);
      } finally {
        DataAcess.remove();
      }
   }

一旦你有一个class实现过滤器的你将它添加到你的web.xml因此:

<!--Filter for adding in dataccess objects-->
<filter>
    <filter-name>DataccessFilter</filter-name>
    <filter-class>my.package.DataccessFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>DataccessFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

页面提供了过滤器及其映射的示例。
DataAccess会看起来像:

public class DataAccess{
    private static ThreadLocal<DataAccess> THREAD_LOCAL = new ThreadLocal();
    private String databasepath;

    public DataAcess(final String databasepath) {
      this.databasepath = databasepath;
    }

    public static DataAccess getInstance() {
      return THREAD_LOCAL.get();
    }
    public static void set(final DataAccess dataAccess) {
      THREAD_LOCAL.set(dataAccess);
    }
    public static void remove() {
      THREAD_LOCAL.remove();
    }
}

非常小心,ThreadLocal因为它可能是 Java 中内存泄漏的第一大原因。对于具有线程池的 Web 服务器,如果您没有正确清除它们,您可能会遇到更严重的错误。

于 2013-02-19T14:06:11.993 回答
0

看起来 ThreadLocal 应该可以帮助您解决用例:

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

此类提供线程局部变量。这些变量不同于它们的正常对应变量,因为每个访问一个(通过它的 get 或 set 方法)的线程都有它自己的、独立初始化的变量副本。

于 2013-02-19T13:59:32.837 回答