web-dev-qa-db-ja.com

Spring AOPリクエストにHttpServletRequestを挿入する方法(カスタムシナリオ)?

コントローラーメソッドに関するAOPアドバイスを作成する標準的な方法を知っています。コントローラーメソッドで宣言されている場合は、HttpServletRequest引数にアクセスできます。

しかし、私のシナリオでは、翻訳サービスがあります。これは現在、翻訳用のユーザーのロケールを維持するセッションスコープです。これによりサービスがステートフルになると思います。また、実際にはシングルトンだと思うので、セッションスコープにしたくありません。ただし、翻訳サービスメソッドが呼び出される場所は複数あるため、これらのメソッドにリクエスト/ロケールを追加するために署名を変更したくありません。問題は、翻訳サービスのメソッドのすべての呼び出し元がHttpServletRequest(コントローラーメソッドではない)にアクセスできないことです。翻訳サービスメソッドに関するアスペクトを記述して、呼び出し元のコンテキストで使用可能かどうかに関係なく、どういうわけか魔法のようにHttpServletRequestにアクセスできますか?

@Service
public class TranslationService {
    public void translate(String key) {
        ...
    }
}

@Aspect
@Component
public class LocaleFinder {
    @PointCut("execution(* TranslationService.translate(..))")
    private void fetchLocale() {}

    @Around("fetchLocale()") // in parameter list
    public void advice(JoinPoint joinpoint, HttpServletRequest request) { .... } 
}

今、翻訳の呼び出し元がHttpServletRequestを持っていない場合、アドバイスでリクエストを受け取ることはできませんか?回避策はありますか?

14
Paddy

翻訳サービスメソッドに関するアスペクトを記述して、呼び出し元のコンテキストで使用可能かどうかに関係なく、どういうわけか魔法のようにHttpServletRequestにアクセスできますか?

簡単ではありません。実際、それは多くの努力を必要とするでしょう。

これを行う簡単な方法は、RequestContextHolderに依存することです。すべてのリクエストで、DispatcherServletは現在のHttpServletRequestRequestContextHolder内の_static ThreadLocal_オブジェクトにバインドします。同じThread内で実行するときに取得できます

_HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
_

これはadvice()メソッドで実行できるため、パラメーターを宣言する必要はありません。

46