1

Jersey RESTful APIの一部としてHK2を使用しています。私はマルチテナント システムで作業しており、ほとんどの API 呼び出しで、テナントはパス パラメーターです。また、次のように、現在、コンストラクターで tenantId を受け入れるいくつかの DAO があります。

public final class WidgetMapper {
    public WidgetMapper(final int tenantId) { .. }
    ..
}

HK2 を使用して、DAO をアプリケーションの他のレイヤーに提供したいと考えています。これを行う正しい方法は何ですか?

  1. コンストラクター引数ではなくセッターを使用するように DAO を変更します。ただ..いや。これtenantIdは、DAO の必要な状態の一部です。

  2. 抽象化のレイヤーを追加します。<interface>MapperFactoryandを作成しますMapperFactoryImpl。これには、引数のないコンストラクターと、 and などの多数のゲッターがgetWidgetMapperありgetGizmoMapperます。ただ..これは面倒そうです。これらの余分なクラスを維持する必要はありません。

  3. 実行時に HK2 がその int 値を WidgetMapper コンストラクターに挿入する魔法の方法はありますか? 次に、tenantId をマッパーに注入し、マッパーを他のクラスに注入します。

  4. ?? 他のHK2マジック?

4

2 に答える 2

0

コンストラクター引数ではなくセッターを使用するように DAO を変更します。ただ..いや。tenantId は、DAO の必須状態の一部です。

あなたのDAOがシングルトンである場合、これがどのように機能するか(または少なくともどのようにきれいに実行できるか)わかりません。

これを行う正しい方法は何ですか?

IMO、最善のアプローチは、1) シングルトン DAO 2) HK2 によってインスタンス化されたときに DAO に挿入され、現在のスレッドに正しいテナント ID を提供するある種のプロキシを使用することだと思います。

これを行うには、次の 2 つの方法が考えられます。

オプション1:

試したことはありませんが、コンストラクター、プライベート フィールド、またはセッターのいずれかを使用して、おそらくUriInfo を DAO に注入できると思います。UriInfo インスタンスから現在の要求のテナント ID を抽出できます。

もし私があなたなら、プライベート フィールドに挿入された UriInfo を取得する DAO の抽象クラスを作成します。次に、 uriInfo.getPathParametersから現在のテナント ID を返す保護されたメソッドを提供します。

public abstract class AbstractDao {

    // jersey/hk2 provides a proxy that references the current thread-bound request
    @Context
    private UriInfo info;

    protected int getTenantId()
    {
        // always returns the tenant id for the current request.  TODO: add
        // logic to handle calls that don't have a tenant id.
        return Integer.valueOf(info.getPathParameters.getFirst("tenantId");
    }
}

オプション 2:

?? 他のHK2マジック?

カスタム注入リゾルバーを作成できます。

もう1つのアイデア...

オプション 3:

HK2 を使用してテナント ID を DAO に挿入しないため、これはあなたの質問に直接答えることはありませんが、言及する価値があると思います。

テナント ID を取得してアプリ内の他のコンポーネントに提供する独自のContainerRequestFilterを実装できます。

デフォルトでは、Jersey はリソース メソッドを解決した後、メソッドが実際に呼び出される前にフィルターを呼び出します。ContainerRequestContextから UriInfo を取得し、テナント ID パス パラメータを取得してから、そのパラメータを独自のスレッド ローカル変数に入れることができます。その後、DAO 内でスレッド ローカルを参照できます。繰り返しますが、基本 DAO クラスに保護されたメソッドを追加して、このロジックをカプセル化することをお勧めします。

ほとんどの API 呼び出しでは、テナントはパス パラメータです。

必要に応じて、 NameBindingを使用して上記の動作を制御できます。

必要に応じて、代わりに通常の ServletFilter を使用してオプション 3 を実装できます。

ノート:

この回答を書いた後、私は、あなたがResourceConfigの拡張に慣れていること、 ServiceLocatorのインスタンスを取得する方法を知っていること、独自の bindings を追加することに慣れていることを想定していたことに気付きました。そうでない場合はお知らせください。詳細を提供するために回答を編集します。

于 2014-01-21T13:43:50.083 に答える