以下は私の側面です。
@Configurable
@Aspect
public class TimingAspect {
@Autowired
private HttpServletRequest httpServletRequest;
// Generic performance logger for any mothod
private Object logPerfomanceInfo(ProceedingJoinPoint joinPoint, String remoteAddress) {
StringBuilder tag = new StringBuilder();
if (joinPoint.getTarget() != null) {
tag.append(joinPoint.getTarget().getClass().getName());
tag.append(".");
}
tag.append(joinPoint.getSignature().getName());
StopWatch stopWatch = new StopWatch(tag.toString());
Object result = joinPoint.proceed(); // continue on the intercepted method
stopWatch.stop();
PerformanceUtils.logInPerf4jFormat(stopWatch.getStartTime(), stopWatch.getElapsedTime(), stopWatch.getTag(), stopWatch.getMessage(), remoteAddress);
return result;
}
@Around("execution(* $$$.$$$.$$$.api.controller.*.*(..))")
public Object logAroundApis(ProceedingJoinPoint joinPoint) throws Throwable {
String remoteAddress = null;
if (httpServletRequest != null) {
remoteAddress = httpServletRequest.getRemoteAddr();
}
return logPerfomanceInfo(joinPoint, remoteAddress);
}
@Around("execution(* $$$.$$$.$$$.$$$.$$$.$$$.*(..))")
public Object logAroundService(ProceedingJoinPoint joinPoint) throws Throwable {
String remoteAddress = null;
if (httpServletRequest != null) {
remoteAddress = httpServletRequest.getRemoteAddr();
}
return logPerfomanceInfo(joinPoint, remoteAddress);
}
コンパイル時エラーは発生しませんが、jettyサーバーを起動すると次の例外が発生します。
ネストされた例外はJava.lang.IllegalStateExceptionです:スレッドバインドリクエストが見つかりません:実際のWebリクエスト以外のリクエスト属性を参照していますか、それとも元の受信スレッド外でリクエストを処理していますか?実際にWebリクエスト内で操作しているにもかかわらずこのメッセージを受信する場合、コードはおそらくDispatcherServlet/DispatcherPortletの外部で実行されています。この場合、RequestContextListenerまたはRequestContextFilterを使用して現在のリクエストを公開します。
ここで注意すべきことは、「logAroundService」メソッドを削除しても例外が発生しないことです。
アスペクトにHttpServletRequest
を自動配線しないでください。これにより、アスペクトが実行中のHttpServletRequest
内から呼び出されるクラスに対してのみ実行可能になります。
代わりに、RequestContextHolder
を使用して、必要なときに要求を取得します。
private String getRemoteAddress() {
RequestAttributes attribs = RequestContextHolder.getRequestAttributes();
if (attribs instanceof NativeWebRequest) {
HttpServletRequest request = (HttpServletRequest) ((NativeWebRequest) attribs).getNativeRequest();
return request.getRemoteAddr();
}
return null;
}
エラーメッセージが言ったように:この場合、RequestContextListenerまたはRequestContextFilterを使用して現在のリクエストを公開します。
修正するには、web.xmlファイルにRequestContextListenerリスナーを登録します。
<web-app ...>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
</web-app>
@M。 Deinumの回答は私には機能しません。代わりにこれらのコードを使用します
RequestAttributes attribs = RequestContextHolder.getRequestAttributes();
if (RequestContextHolder.getRequestAttributes() != null) {
HttpServletRequest request = ((ServletRequestAttributes) attributes).getRequest();
return request.getRemoteAddr();
}
ポイントカット式を使用すると、基本的にすべてのBeanをプロキシし、そのアドバイスを適用します。いくつかのBeanが存在し、HttpServletRequest
のコンテキスト外で動作します。これは、取得できないことを意味します。
HttpServletRequest
は、サーブレットコンテナリクエスト処理スレッドが通過する場所にのみ挿入できます。