6

@Context依存性注入が HttpServletRequest または HttpServletResponse の代わりに $Proxy(乱数) インスタンスのコレクションを返す理由を理解するのに少し問題があります。

私はGlassfish 3.1.2.2をJerseyのバージョン(Jersey: 1.11.1)で使用しており、私のアプリはEARアプリケーションとして構築されています。

メソッドに注釈を付ける単純な @Remote インターフェイスがあり、REST サービスは問題なく動作しますが、HttpServletRequest 情報にアクセスしようとすると問題が発生します。

セッション Bean のプライベート フィールドに注釈を付けました。

@Context
private HttpServletRequest request;
@Context
private HttpServletResponse response;

また、パラメーターのセットとして @Context を含めるメソッド シグネチャも作成しました。

@POST
@Path("authenticate")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response authenticate(@FormParam("username") String username, @FormParam("password") String password, @Context HttpServletRequest request, @Context HttpServletResponse response); 

エントリの直後にメソッドをデバッグしようとすると、ローカル メソッド インスタンスが $ProxyXXX タイプであるのに対し、グローバル リクエストおよびレスポンス オブジェクトが null であることがわかります。

問題は、これらのオブジェクトにアクセスできない (またはその方法がわからない) ことです。ウェブ上のチュートリアルによると、それらは私が利用できるはずですが、これらにアクセスしようとすると、これがスローされます:

WARNING: StandardWrapperValve[RestDataService]: PWC1406: Servlet.service() for servlet RestDataService threw exception
java.lang.IllegalStateException: No thread local value in scope for proxy of class $Proxy245
    at com.sun.jersey.server.impl.ThreadLocalInvoker.invoke(ThreadLocalInvoker.java:93)
    at $Proxy245.getContextPath(Unknown Source)

これは私がこれらを呼び出そうとしている方法です (この例では単に getContextPath を呼び出します)

@Override
public Response authenticate(String username, String password, HttpServletRequest request, HttpServletResponse response) {

    System.out.println("just a test: " + request.getContextPath());

ここで何が欠けていますか?誰かが同様の問題を経験しましたか?

グレッグ

4

2 に答える 2

9

この問題を理解するには、スコープの仕組みを理解する必要があります。何が起こるかを説明するために、ここに例を示します。これを持っているとします

@Singleton
@Path("..")
public class SomeResource {

    @Context
    private HttpServletRequest request;
}

この状況がもたらす問題は、HttpServletRequestリクエストごとに が生成されることですが、リソース クラスはシングルトンであるため 1 回しか作成されないため、最初はHttpServletRequestシングルトンが作成されたときに注入するものはありません。

この問題を解決するために、Jersey はプロキシを挿入します。概念的には、結果は次のようになります

@Singleton
@Path("..")
public class SomeResource {

    @Context
    private ProxyHttpServletRequest proxyRequest;
}

リクエストが来ると、実際はスコープ contextHttpServletRequest入れられます。これは正確な実装ではありませんが、スコープ コンテキストを次のように想像できます。ThreadLocal

public class RequestScopeContext {
    private static final ThreadLocal<HttpServletReqest> request
            = new ThreadLocal<>();

    public static HttpServletRequest get() { .. }
    public static void setRequest(HttpServletRequest request) { .. }
}

リクエストが来るとHttpServletRequest、コンテキストに設定されます。HttpServletRequestまた、内で の呼び出しが行われると、実際には からの要求を取得して呼び出しを転送するSomeResourceプロキシ オブジェクトで行われます。ThreadLocal概念的には、次のように見えると想像します

class ProxyHttpServletRequest {
    public String getContextPath() {
        HttpServletRequest request = RequestScopeContext.get();
        return request.getContextPath();
    }
}

代わりにこれがあるとします

@Singleton
@Path("..")
public class SomeResource {

    @GET
    public Response get(@Context HttpServletRequest request) {
        ...
    }
}

これとの違いは、リクエストがフィールドに挿入されなくなったため、プロキシが必要ないことです。メソッドへのHttpServletRequest呼び出しが行われる場合にのみ必要です。したがって、Jersey はプロキシではなく実際のリクエストを挿入します。

このパターンは、Jersey だけに固有のものではないことに注意してください。どのフレームワークも DI であり、スコープが関係していて、スコープの小さいオブジェクトをより広いスコープのオブジェクトに挿入しようとすると、同様のプロキシ パターンが使用されます。


OPへ:これはあなたの正確な問題ではありません。上記の回答は、プロキシについて疑問を持っている大多数の人々に役立つ可能性が高くなります。

あなたの場合、EJBに を注入しようとしていると言いHttpServletRequestました。1つには、それが@Remote可能である、または可能であることさえ知りませんでした。私の推測では、EJB エンジンは. したがって、Jersey がそれを呼び出そうとすると、コンテキストには何もありません。ThreadLocal

アノテーションは、@ContextEJB 用ではなく、JAX-RS コンポーネント用です。個人的にはHttpServletRequest、EJB をあまり扱っていないので、EJB に an を注入する方法がわかりません。したがって、あなたの正確な問題に直面している人は、その方法を検索する必要があります。しかし、私が言ったように、それがこの質問を検索する人の大多数ではないと思います。リクエストが実際のリクエストではなくプロキシである理由を単に疑問に思っていると思います。したがって、この答えは彼らに向けたものです。

于 2015-10-04T18:57:53.077 に答える
0

セッションとコンテキストの適切なオブジェクトを取得するのと同じ問題ではありません。このように、私にとってはうまくいきます。

   public login login(request Request,@Context MessageContext context) {

                 HttpServletRequest httpServletRequest = context
                              .getHttpServletRequest();

}

于 2015-10-04T17:58:05.717 に答える