6

クラスとメソッド、リモート IP アドレス、応答時間などの一般的なデータをログに記録するために使用したい @AroundInvoke REST Web サービス インターセプターがあります。

クラスとメソッド名の取得は InvocationContext を使用して簡単に行うことができ、リモート IP は HttpServletRequest を介して利用できます (傍受される REST サービスのパラメーター リストに @Context HttpServletRequest が含まれている場合)。

ただし、一部の REST メソッドにはパラメーターに HttpServletRequest が含まれていないため、これらの場合に HttpServletRequest オブジェクトを取得する方法がわかりません。

たとえば、次の REST Web サービスには @Context HttpServletRequest パラメーターがありません。

@Inject
@Default
private MemberManager memberManager;

@POST
@Path("/add")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Member add(NewMember member) throws MemberInvalidException {
    return memberManager.add(member);
}

インターセプターに直接注入しようとしましたが、(JBoss 6.1 では) 常に null です...

public class RestLoggedInterceptorImpl implements Serializable {
    @Context
    HttpServletRequest req;

    @AroundInvoke
    public Object aroundInvoke(InvocationContext ic) throws Exception {

        logger.info(req.getRemoteAddr());  // <- this throws NPE as req is always null
        ...
        return ic.proceed();

REST サービスにパラメーターが含まれているかどうかに関係なく、HttpServletRequest オブジェクトにアクセスするための信頼できる方法、または単に Http ヘッダーにアクセスするためのアドバイスが必要です。

4

3 に答える 3

5

Javadoc http://docs.oracle.com/javaee/6/api/javax/interceptor/package-summary.htmlでインターセプターのライフサイクルを調査した後、それ以外のサーブレットコンテキスト情報にアクセスすることは不可能だと思いますInvocationContext (基礎となる REST 定義のパラメーターによって定義されます)。これは、Interceptor インスタンスが基礎となる Bean と同じライフサイクルを持ち、サーブレット リクエスト @Context をインスタンスではなくメソッドに注入する必要があるためです。ただし、@AroundInvoke を含む Interceptor は、メソッド シグネチャに InvocationContext 以外のものがある場合はデプロイされません。追加の @Context パラメータは受け入れません。

したがって、Interceptor が HttpServletRequest を取得できるようにするために思いつく唯一の答えは、基礎となる REST メソッドの定義を変更して @Context HttpServletRequest パラメーター (および必要に応じて HttpServletResponse) を含めることです。

@Inject
@Default
private MemberManager memberManager;

@POST
@Path("/add")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Member add(NewMember member, @Context HttpServletRequest request, @Context HttpServletResponse response) throws MemberInvalidException {
    ...
}

次に、インターセプターは InvocationContext のパラメーターを反復処理して、HttpServletRequest を取得できます。

@AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
    HttpServletRequest req = getHttpServletRequest(ic);
    ...
    return ic.proceed();
}

private HttpServletRequest getHttpServletRequest(InvocationContext ic) {
    for (Object parameter : ic.getParameters()) {
        if (parameter instanceof HttpServletRequest) {
            return (HttpServletRequest) parameter;
        }
    }
    // ... handle no HttpRequest object.. e.g. log an error, throw an Exception or whatever
于 2013-07-08T07:23:50.757 に答える