10

ExceptionMapper を実装する単一インスタンス クラスがあります。これは静的クラスではありませんが、単一のインスタンスのみが作成されることがわかっているクラスです(確認しました-コンストラクターは1回だけ呼び出されます)。

私のクラスは@Context HttpServletRequestを使用しており、私のExceptionMapper.toResponse()メソッドが呼び出されると、@Context 'request'パラメータに、例​​外がスローされるリクエストに関連する値があることを明確に観察できます。

ドキュメントによると 、これは実際に設計によってサポートされている機能であり、「プロキシ」を使用して行われます。

これがどのように正確に実装されているのだろうか-単一のインスタンスが異なるメンバー変数の値を同時に持つことができる方法は?

ありがとう、
AG

PS: テスト コードは次のとおりです。

@Provider
public class MyExceptionMapper implements ExceptionMapper<Exception> {

    public MyExceptionMapper() {
        System.out.println("CTOR!!");
    }

    @Context HttpServletRequest req;

    public static boolean done = false;  
    public Response toResponse(Exception ex) {
        if (!done) {
            done = true;
            Thread.sleep(10000);
        }
        System.out.println(req.getRequestURI());
        return null;
    }
}

私のRESTハンドラーメソッドは例外をスローするため、次の2つのリクエストを「並行して」実行すると(上記のスリープにより、2番目のリクエストが到着したときに最初のリクエストが終了していないことが確認され、IMHOは唯一の「req」フィールドを変更する必要があります):

- http://localhost/app/one
- http://localhost/app/two

私のプログラムは次のように出力します:

CTOR!
http://localhost/app/one
http://localhost/app/two
4

1 に答える 1

6

観察した効果を実現する最も簡単な方法は、注入されたHttpServletRequestオブジェクトを実際にプロキシ オブジェクト、つまり実際 HttpServletRequestの のスレッド対応デリゲートにすることです。デリゲートでメソッドを呼び出す場合、メソッドは正しい実際のオブジェクトを (たとえば、スレッド ローカル変数を介して) 検索し、そのオブジェクトに呼び出しを渡すだけです。この戦略は比較的簡単に正しく行うことができます。また、インターフェイスであるため、フィールド アクセスについて心配する必要はまったくありません (プロキシするのはかなりトリッキーです)。

このようなプロキシ オブジェクトを作成するには、いくつかの方法があります。具体的には、インターフェイスを直接実装することによって実行することも、Java の一般的な動的プロキシ メカニズム(任意のインターフェイスのプロキシを構築できる) をHttpServletRequest介してより一般的に実行することもできます。ランタイム コードの生成など、他にもより複雑な可能性がありますが、ここでは不要です。OTOH、直接実装されてもまったく驚かないでしょう。これは JAX-RS 実装にとってやや重要なクラスです…</p> HttpServletRequest

于 2013-07-20T20:31:44.170 に答える