実際には、パトリシアは、AOPの側面に統一された印刷要求のログを使用する方法についての記事の前に出て行って、なぜあなたは1の外に出るのでしょうか?書くことは何もありませんか?
ハハ、もちろんありません!その理由は、実装は次のような理由から、まだ欠陥がありました。
- この方法は、我々は不可能とのインターフェイスパラメータのログを印刷したくない場合は、死んでカットカットされたすべてのコントローラのメソッドであるためには、十分に柔軟ではありません。
- コントローラ・パッケージ・レベルが深すぎ、より少ないパッケージを切断多くのインターフェースをもたらします。
今日では、春ブーツでAOPを達成するためにどのようにカスタム注釈の方法についての主な話は、統一されたプリントアウト参照ログをカット。リトル友人が波を収集することができます。
ADOは、ポイントを取得します!
まず、ログ出力カット効果を見てみましょう
実装方法を見て前に、私たちは効果Zeyangログ出力セクションを見てみましょう。
図からわかるように、各要求については、それぞれ、始まり、一目で終了し、次のパラメータを出力します。
- URL:インターフェイスアドレスを要求します。
- 説明:中国のインタフェース記述情報。
- HTTPメソッド:リクエストのメソッドである
POST
、GET
またはDELETE
等。 - クラスメソッド:メソッドのパスが要求されます。パッケージ名+メソッド名。
- IP:要求元のIPアドレス。
- Argsの要求:要求パラメータ、出力JSON形式。
- 応答のArgs:基準出力JSON形式に応じて、
- 時間のかかる:各インターフェイスの性能指標を推定するために、時間のかかる要求。
どうでしょうか?それはかなり良い効果が見えますか?次に、どのようにそれを実装するためにステップバイステップ私たちを見てみましょうか?
第二に、AOPのMavenは依存しています追加
プロジェクトでは pom.xml
、ファイルの依存関係を追加します。
<!-- aop 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!-- 用于日志切面中,以 json 格式打印出入参 --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency>
第三に、カスタムログノート
次のように私たちは、ログノートをカスタマイズしてみましょう:
- ①:この注釈を使用したときに実行するとき、私たちは定義します。
- ②:我々は法に作用するように定義何のための注意事項。
- ③:JavaDocのに含めるかどうかのアノテーション。
- ④:Notes名前付き
WebLog
。 - ⑤:プロパティの定義は、デフォルトでは空の文字列です。
次のようにソースコードは次のとおりです。
package site.exception.springbootaopwebrequest.aspect;
import java.lang.annotation.*;
/**
* @author 犬小哈 (微信号:小哈学Java)
* @site www.exception.site * @date 2019/2/12 * @time 下午9:19 * @discription **/ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Documented public @interface WebLog { /** * 日志描述信息 * * @return */ String description() default ""; }
ここでは、完全なカスタム注釈の定義は完了です。
第四に、AOP部の構成
AOPの側面を設定する前に、我々は次を理解する必要があり aspectj
効果に関連する注釈を:
- @Aspect:注釈クラスとしてクラスを宣言。
- @Pointcut:式続いてカット点の定義、表現カットアノテーションとして定義することができ、この方法はまた、特定のパッケージに切断することができます。
良いカットポイントが定義された後、それがこのカットオフ点の周りに大騒ぎです。
- @Before:接点前に、関連するコードに織り込ま。
- @After:カット点の後、関連するコードに織り込ま。
- @AfterReturning:コンテンツの接点に戻った後、関連するコードに織り込ま、一般戻り値処理シーンを行うために使用されます。
- @AfterThrowing:コードに織り込まれたときに、処理のため処理ロジックは、例外をスロー。
- @Around:サラウンドとエントリポイントの前後コードに織り込まれるため、カットポイントを実行するときに自由に制御することができます。
次に、定義 WebLogAspect.java
セクションクラスを、カットポイントを宣言します。
次に、定義し @Around
実行するときのために囲まれた接触点を:
- ①:コール・インタフェースの開始時間についての記録。
- ②:呼び出すために@Beforeうカットポイントを実行した後、接点を行う - >インタフェースロジックコード - > @After - > @AfterReturning。
- ③:パラメータをプリントアウト。
- ④:印刷インタフェース時間のかかるプロセス;
- ⑤:インタフェースは参照結果を返し。
のは、見てみましょう @Before
方法:
それは非常に明確であるため、コメントは正しいです、説明の注釈を参照してください!
最後に、 @After
終了します。
最後に、我々は、ログは、各インターフェイスの終わりをマークし、印刷します。最後に、プロジェクトのパッケージ構造を見てみましょう。
ここでは、コードの関連セクションは完了です!
完全なコード:
package site.exception.springbootaopwebrequest.aspect;
import com.google.gson.Gson;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; /** * @author 犬小哈 (微信号:小哈学Java) * @site www.exception.site * @date 2019/2/12 * @time 下午9:19 * @discription **/ @Aspect @Component @Profile({"dev", "test"}) public class WebLogAspect { private final static Logger logger = LoggerFactory.getLogger(WebLogAspect.class); /** 换行符 */ private static final String LINE_SEPARATOR = System.lineSeparator(); /** 以自定义 @WebLog 注解为切点 */ @Pointcut("@annotation(site.exception.springbootaopwebrequest.aspect.WebLog)") public void webLog() {} /** * 在切点之前织入 * @param joinPoint * @throws Throwable */ @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { // 开始打印请求日志 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 获取 @WebLog 注解的描述信息 String methodDescription = getAspectLogDescription(joinPoint); // 打印请求相关参数 logger.info("========================================== Start =========================================="); // 打印请求 url logger.info("URL : {}", request.getRequestURL().toString()); // 打印描述信息 logger.info("Description : {}", methodDescription); // 打印 Http method logger.info("HTTP Method : {}", request.getMethod()); // 打印调用 controller 的全路径以及执行方法 logger.info("Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()); // 打印请求的 IP logger.info("IP : {}", request.getRemoteAddr()); // 打印请求入参 logger.info("Request Args : {}", new Gson().toJson(joinPoint.getArgs())); } /** * 在切点之后织入 * @throws Throwable */ @After("webLog()") public void doAfter() throws Throwable { // 接口结束后换行,方便分割查看 logger.info("=========================================== End ===========================================" + LINE_SEPARATOR); } /** * 环绕 * @param proceedingJoinPoint * @return * @throws Throwable */ @Around("webLog()") public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { long startTime = System.currentTimeMillis(); Object result = proceedingJoinPoint.proceed(); // 打印出参 logger.info("Response Args : {}", new Gson().toJson(result)); // 执行耗时 logger.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime); return result; } /** * 获取切面注解的描述 * * @param joinPoint 切点 * @return 描述信息 * @throws Exception */ public String getAspectLogDescription(JoinPoint joinPoint) throws Exception { String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); StringBuilder description = new StringBuilder(""); for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { description.append(method.getAnnotation(WebLog.class).description()); break; } } } return description.toString(); } }
第五に、どのようにそれを使用するには?
私たちのカットオフ点は、カスタム注釈であるため @WebLog
、私たちはただ、各コントローラのコントローラ・インタフェース・メソッドで@WebLogを追加する必要があり、我々はそれにコメントすることなく、インタフェース参照ログを印刷したくない場合は、注釈を付けることができます。
第六に、ファイルのアップロードHaoshiのためではありませんか?
不自由さ!単一ファイルのアップロード、またはマルチファイルのアップロードかどうか、ログを切るだけでなく実行している、ここでテストしたもの、パトリシアが出て投稿されていません。興味の小さなパートナーを試すことができます!
七、開発およびテスト環境で使いたいですか?
高いパフォーマンスを必要とするアプリケーションでは、本番環境でログを印刷したくない、あなたは、開発環境やテスト環境で使用したい、どのようにそれを行うには?我々は唯一のセクションを追加する必要があり @Profile
、以下に示すように、上:
これはのみに影響を指定する dev
開発環境と test
テスト環境、本番環境が prod
有効ではありません!
どのように優先順位を割り当てるために8マルチスライス?
私たちのサービスが複数のセクション、あなたはログを印刷したいのですが、またその上のトークンをチェックし、より多くのWeb層のために例えば、我々のインタフェースで定義されているとしましょう。優先順位、それをカットする方法を指定するには?これは、セクションの実行順序を指定する方法ですか?
私たちはできる @Order(i)
注釈の優先順位の注目を指定します。優先順位は高く、I値より小さい。
我々はログ優先度のこのセクションでは上記で定義されているとしましょう @Order(10)
、我々はチェックしてい token
セクションのを CheckTokenAspect.java
、私たちは順番を定義し @Order(11)
、次のように、それらの間の実行順序は次のとおりです。
私たちは、要約することができます:
- 、カット点の前に
@Order
小から大までが行われ、それが優先順位が高い小さいと言うことです。 - カットポイント後、
@Order
下降、すなわちより大きな、より高い優先度、実行されます。
ナイン、文献
http://blog.didispace.com/springbootaoplog
テン、GitHubのソースアドレス
https://github.com/weiwosuoai/spring-boot-tutorial/tree/master/spring-boot-aop-web-request
転載:https://www.exception.site/springboot/spring-boot-aop-web-request