出典ます。https://macrozheng.github.io/mall-learning/#/technology/aop_log
AOP
AOPを意味し、アスペクト指向プログラミングのための略語です:アスペクト指向プログラミングを、ダイナミックエージェントプログラムは、プリコンパイルの方法と実行によって維持統一を達成するための技術を採用しています。AOPは、開発の効率を向上させつつ、ビジネス・ロジックは、プログラムの再利用性を向上させ、部品間の結合の程度を低減するようなビジネス・ロジックの各部分を分離するために使用することができます。
AOP関連の用語
通知(アドバイス)
通知部は、やるべき仕事とする場合について説明しています。例えば、我々は、ログ・レコードは、各インターフェイスの期間を呼び出すカットする必要がある、あなたは、別途インターフェース呼び出しの前と後に現在の時刻を記録し、その後、差をとる必要があります。
- 事前通知(前):ターゲット・メソッド呼び出しの前に通知機能を呼び出します。
- アドバイスを帰国後(後):メソッドを気にしない、ターゲット・メソッドの呼び出し後の通知機能を呼び出して結果を返します。
- 通知(AfterReturningを)返します:ターゲット・メソッドが成功した後、通知機能を呼び出します。
- 例外通知(AfterThrowing):ターゲットメソッドは例外をスローした後、通知機能を呼び出します。
- アドバイス(アラウンド)周り:通知対象のメソッド呼び出しカスタムの実行前と後の行動、客観的な方法を包みました。
接続点(ジョインポイント)
通知機能は、タイミングが適用されます。例えば、インタフェースメソッドが呼び出されたときには、接続点のログを切断することです。
タンジェントポイント(ポイントカット)
カット点の範囲通知機能が適用される定義します。このようなログのようなアプリケーションは、すべてのインターフェイス、コントローラ層の、すなわち、すべてのインタフェース方法を切断します。
セクション(アスペクト)
通知部は、いつ、どこで通知を適用するために定義するカット点の組み合わせです。
はじめに(はじめに)
変更せずに既存のクラスの場合、または既存のクラス属性に新しいメソッドを追加します。
ウィービング(ウィービング)
ターゲットオブジェクトにカットし、プロセスの新しいプロキシオブジェクトを作成します。
春の注釈には、セクションを作成するために使用されます
関連の注意事項
- @Aspect:セクションを定義するために使用
- @Before:通知方法は、対象のメソッド呼び出しの前に実行されます
- @After:通知方法は、ターゲットメソッドが戻った後に実行するか、例外をスローします
- @AfterReturning:通知方法は、ターゲットメソッドの復帰後に実行されます
- @AfterThrowing:ターゲットメソッドの実行後の通知方法は、例外をスローします
- @Around:通知方法は、ターゲットメソッドをカプセル化します
- @Pointcut:カットポイント定義された式
カットポイント式
通知の範囲は、表現形式を適用することを指定します。
実行(メソッドの修飾子戻りパケットはメソッドの型に属する。クラス名。メソッド名(パラメータ法)
// publicメソッドは、セクションに適用されているすべてのクラスのcom.macro.mall.tiny.controllerパッケージには、通知 が実行される(公衆 * com.macro.mall.tiny.controllerを。*。* (..)) // COM。すべてのメソッドは、パッケージと、すべてのパケットのためにそのサブクラスは、通知アプリケーションにカットされmacro.mall.tiny.service 実行(com.macro.mall.tiny.service .. * *。* (..)) // COMすべてのメソッドは、通知に.macro.mall.tiny.service.PmsBrandServiceクラスの項を適用し 、実行(* com.macro.mall.tiny.service.PmsBrandService。*(.. ))
AOPのセクションでは、インターフェイスのロギングを実装して追加します。
ログ情報パッケージタイプウェブログを追加
操作、時間、経過時間、URL、リクエストパラメータと戻り結果情報の説明を含めて、記録されるログ情報のパッケージ。
パッケージcom.xc.mall2.dto; インポートlombok.Getter; インポートlombok.Setter; インポートlombok.ToString; / ** *コントローラベースの封止層をログ に作成190903.によって* XC ONに * / @Getter @Setter @ToString 公衆 クラスウェブログ{ / ** *操作説明 * / プライベート文字列の記述; / ** *操作のユーザー * / プライベート文字列名; / ** *動作時間 * / プライベートロングたstartTime; / ** *経過時間 * / プライベート整数spendTime ; / ** *ルート * / プライベート文字列basePathを; / ** * URI * / プライベート文字列URI; / ** * URL * / プライベート文字列のURL; / ** *リクエストの種類 * / プライベート文字列メソッド; / ** * IPアドレス * / プライベート文字列IP; / ** *リクエストパラメータ * / プライベートオブジェクトのパラメータ; / ** *のリクエストの結果を返す * / プライベートオブジェクトの結果を、 }
カットクラスWebLogAspectを追加
セクションでは、ログを定義し、サラウンドで取得したログ情報は、通知、コントローラ層を必要として行くためにすべてのパブリックメソッドに適用されます。
パッケージcom.xc.mall2.component。 輸入cn.hutool.core.util.StrUtil; 輸入cn.hutool.core.util.URLUtil; 輸入cn.hutool.json.JSONUtil; 輸入com.xc.mall2.dto.WebLog。 輸入io.swagger.annotations.ApiOperation。 輸入org.aspectj.lang.JoinPoint。 輸入org.aspectj.lang.ProceedingJoinPoint。 輸入org.aspectj.lang.Signature。 輸入 org.aspectj.lang.annotation *。; 輸入org.aspectj.lang.reflect.MethodSignature。 輸入org.slf4j.Logger。 輸入org.slf4j.LoggerFactory; インポートorg.springframework.core.annotation.Order; 輸入org.springframework.stereotype.Component。 輸入org.springframework.util.StringUtils。 輸入org.springframework.web.bind.annotation.RequestBody。 輸入org.springframework.web.bind.annotation.RequestParam。 輸入org.springframework.web.context.request.RequestContextHolder。 輸入org.springframework.web.context.request.ServletRequestAttributes。 インポートのjavax.servlet.http.HttpServletRequest; 輸入java.lang.reflect.Methodオブジェクト。 輸入java.lang.reflect.Parameter。 輸入はjava.util.ArrayList; インポートjava.util.HashMapを; 輸入はjava.util.List; 輸入java.util.Map; / ** *统一日志处理切面 * 190903.にXCによって作成 * / @Aspect @Component @Order( 1 ) パブリック クラスWebLogAspect { プライベート 静的 最終ロガーロガー= LoggerFactory.getLogger(WebLogAspect。クラス)。 @Pointcut( "実行(公開* com.xc.mall2.controller。*。*(..))" ) 公共 ボイドブログ(){ } @Before( "ウェブログ()" ) 公共 ボイドdoBefore(ジョインポイントジョインポイント)がスローされたThrowable { } @AfterReturning(値 = "RET"を返す= "ウェブログ()" ) 公共 ボイド doAfterReturning(オブジェクトRET)がスローされたThrowable { } @Around( "ウェブログ()" ) パブリックオブジェクトdoAround( ProceedingJoinPointジョインポイント)がスローされたThrowableを{ 長いのstartTime = にSystem.currentTimeMillis(); // 获取当前请求对象 ServletRequestAttributes属性=(ServletRequestAttributes)RequestContextHolder.getRequestAttributesを(); HttpServletRequestのリクエスト = attributes.getRequest()。 // 记录请求信息 ウェブログウェブログ= 新しいウェブログ(); オブジェクトの結果 = joinPoint.proceed()。 署名署名 = joinPoint.getSignature()。 MethodSignature methodSignature = (MethodSignature)署名。 方法メソッド = methodSignature.getMethod()。 もし(method.isAnnotationPresent(ApiOperation クラス)){ ApiOperation apiOperation = method.getAnnotation(ApiOperation クラス)。 webLog.setDescription(apiOperation.value())。 } 長い endTimeは= webLog.setUri(request.getRequestURI())。System.currentTimeMillis(); ストリングurlStr = 。request.getRequestURL()のtoString(); webLog.setBasePath(StrUtil.removeSuffix(urlStr、URLUtil.url(urlStr).getPath()))。 webLog.setIp(request.getRemoteUser())。 webLog.setMethod(request.getMethod())。 webLog.setParameter(のgetParameter(メソッド、joinPoint.getArgs()))。 webLog.setResult(結果)。 webLog.setSpendTime((int型)(endTimeは- のstartTime)); webLog.setStartTime(のstartTime)。 webLog.setUrl(request.getRequestURL()のtoString())。 LOGGER.info( "{}" 、JSONUtil.parse(ウェブログ))。 リターン結果; } / ** *取得要求パラメータとパラメータ渡される方法に従って * / プライベートオブジェクトのgetParameter(メソッド、メソッド、オブジェクト[]引数){ リスト <OBJECT> = argListに新しい新規のArrayList <> (); パラメータ[]パラメータ = method.getParameters() のために(INT I = 0; Iは、パラメータ<長さ; I ++ ){ // 要求パラメータとして変性注釈RequestBodyパラメータ RequestBody requestBody =パラメーター[I] .getAnnotation(RequestBody。クラス)。 もし!(requestBody = NULL ){ argList.add(引数[I])。 } // 将RequestParam注解修饰的参数作为请求参数 。RequestParam requestParam =パラメーター[I] .getAnnotation(RequestParam クラス;) もし!(requestParam = NULL ){ マップの<string、オブジェクト>マップ= 新しいです HashMapの<> (); 文字列キー = パラメーター[I] .getName(); 場合(!StringUtils.isEmpty(requestParam.value())){ キー = requestParam.value()。 } map.put(キー、引数[I])。 argList.add(マップ) } } IF(argList.size()== 0 ){ 戻り ヌル。 } そう であれば(argList.size()== 1 ){ 戻り argList.getを(0 )。 } 他{ 戻りargListにします。 } } }
インターフェース・テスト:
2019年9月3日16:48:31.866 INFO 14208 --- [NIO-8080-EXEC-2] com.xc.mall2.component.WebLogAspect:{ "結果":{ "コード":200、 "データ": { "合計":11、 "TOTALPAGE":11、 "pageSizeを":1、 "リスト":[{ "productCommentCount" 100、 "名称": "万和"、 "bigPic": ""、 "ロゴ" : "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180607/timg(5).jpg"、 "のshowStatus":1、 "ID":1、 "ソート": 0、 "productCount" 100、 "firstLetter": "W"、 "factoryStatus":1}]、 "PAGENUMは":1}、 "メッセージ": "操作成功"}、 "basePathを": "HTTP://ローカルホスト:8080" 、 "方法": "GET"、 "IP": "テスト"、 "パラメータ":[{ "PAGENUM":1}、{」pageSizeを ":1}]、" 説明 ":" 分页查询品牌列表 " "のstartTime":1567500511861、 "URI": "/ブランド/リスト"、 "URL":" にhttp:// localhost:8080 /ブランド/リスト」、 "spendTime":5}