7

GlassFishでRESTfulJavaバックエンドを実行しています。これに接続されているのはHTML5/JSフロントエンドで、これをWebアプリケーションプロジェクトに配置するか(依存関係としてバックエンドを含める)、別の場所にあるIISWebサーバーで実行できます。CORSは問題ではありません。この次の問題を解決するものは何でも:

状況:

  1. User1がログオンし、データベースパスが「db /user1/」に設定されます
  2. User1は「値1」をデータベースに挿入します
  3. User2がログオンし、データベースパスが「db /user2/」に設定されます
  4. User1がデータベースから「値1」を削除しようとしています

データベースパスがdb/user2に変更されており、そのデータベースに値1がないため、User1はdb/user1から値1を削除できません。

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

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

getInstance()メソッドを変更して、シングルトンとして機能するようにするにはどうすればよいですか?ただし、そのユーザーのスレッド内でのみ機能しますか?スレッドローカルと呼ばれるものを見ましたが、それを完全には理解していませんでした。それはおそらく解決策ですか?

どんな助けでも大歓迎です。

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();
    }
}

ただし、これによりメモリ リークが発生します。したがって、サーブレット フィルターを使用して、リクエストの開始時に値を設定し、最後にそれを削除する必要があります。

   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();
      }
   }

Filterclassを実装する を取得したら、それを次のように追加します。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();
    }
}

これはおそらく Java でのメモリ リークの最大の原因であるため、細心の注意を払ってください。ThreadLocalスレッド プールを備えた 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 に答える