1。概要
一般的なシステムでは、システムへのログイン、ユーザーの追加、ユーザーの削除など、いくつかの重要な操作を実行する場合、これらの動作を維持する必要があります。この記事では、Spring AOPとJavaのカスタム注釈を介してログ挿入を実装します。このソリューションは、元のビジネスへの侵入が少なく、実現により柔軟に対応しています
2。ログの関連クラス定義
ログを2つのクラスに抽象化します:機能モジュールと操作タイプ
列挙クラスを使用して、学生やユーザーモジュールなどの関数モジュールタイプモジュールタイプを定義します
public enum moduleType {default( "1")、//デフォルト値学生( "2")、//学生モジュール教師( "3"); //ユーザーモジュールPrivate ModuleType(String Index){this.module = index; }プライベート文字列モジュール; public string getModule(){return this.module; }}列挙クラスを使用して、操作のタイプ:EventTypeを定義します。ログイン、追加、削除、更新、削除など。
public enum eventType {default( "1"、 "default")、add( "2"、 "add")、update( "3"、 "update")、delete_single( "4"、 "delete-single")、login( "10"、 "login")、login_out( "11"、 "login_out"); private eventType(string index、string name){this.name = name; this.event = index; }プライベート文字列イベント;プライベート文字列名; public string getevent(){return this.event; } public string getname(){return name; }}3.ログ関連の注釈を定義します
3.1。 @Logenable
ここでは、ログのスイッチ数量を定義します。この値がクラスで真である場合にのみ、このクラスのログ関数が有効になります。
@documented @retention(retentionPolicy.runtime)@target({elementType.type})public @interface logenable { / ** * trueの場合、クラスの下のロゲベントが有効になります。3.2。 @logevent
ここのログの定義。この注釈がクラスで注釈が付けられている場合、このパラメーターはクラスのすべての方法のデフォルト値として使用されます。注釈がメソッドにある場合、この方法でのみ機能します
@documented@retention(retentionPolicy.runtime)@target({java.lang.annotation.ElementType.Method、elementType.type})public @interface logevent {moduleType Module()default moduleType.default; // logがeventType event()default eventType.defaultを属するモジュール。 //ログイベントタイプ文字列desc()default ""; //説明情報}3.3。 @logkey
この注釈がメソッドにある場合、メソッド全体のパラメーターはJSON形式のログに保存されます。この注釈がメソッドとクラスの両方で注釈が付けられている場合、メソッドの注釈はクラスの値を上書きします。
@target({elementType.field、elementType.parameter})@retention(retentionpolicy.runtime)@documentedpublic @interface logkey {string keyname()default ""; // key boolean isuserid()default falseの名前。 //このフィールドがこの操作のユーザーIDであるかどうか、ここではboolean islog()default trueが省略されています。 //ログに追加されたかどうか}4.ログ処理クラスを定義します
4.1。 logadmmodel
ログ情報を保持するクラスを定義します
パブリッククラスlogadmmodel {private long id; Private String userid; //ユーザープライベート文字列ユーザー名を操作します。プライベートストリングAdmmodel; //モジュールプライベート文字列admevent; //操作private Date Createdate; //操作コンテンツプライベート文字列admoptcontent; //操作コンテンツプライベート文字列desc; // berems set/oficted}4.2。 ILOGMANAGER
ログ処理のためにインターフェイスクラスiLogmanagerを定義します
Redis、MQなどの場合、ログをデータベースに保存したり、ミドルウェアを開いたりすることができます。各ログ処理クラスは、このインターフェイスの実装クラスです。
パブリックインターフェイスilogmanager { / ***ログ処理モジュール* @param paramlogadmbean* / void deallog(logadmmodel paramlogadmbean);}4.3。 dblogmanager
ログを保存するためのILOGMANAGER実装クラス。ここではシミュレートされたストレージのみ
@servicepublic class dblogmanagerはilogmanager {@override public void deallog(logadmmodel paramologadmbean){system.out.println( "ログをデータベースに保存します。ログの内容は次のとおりです。 }}5。AOP構成
5.1。 LogaSpectはAOPクラスを定義します
このクラスに@Aspectで注釈を付けます
@pointcutを使用して、パッケージとクラスの方法を定義して傍受
@Aroundを使用してメソッドを定義します
@component @sasdpublic class logaspect {@autowired private loginfogeneration loginfogeneration; @autowired private ilogmanager logmanager; @pointcut( "execution(*com.hry.spring.mvc.aop.log.service ..* }} ManagerLogpointの周り:メインメソッドの主なビジネスプロセス
1.インターセプトメソッドのクラスが@Logenableによって注釈が付けられているかどうかを確認してください。その場合、ログロジックに従います。それ以外の場合は、通常のロジックが実行されます。
2。インターセプトメソッドが@logeventであるかどうかを確認してください。その場合、ログロジックに従います。そうしないと、通常のロジックが実行されます。
3.取得方法に基づいて@logeventの中央値を取得し、ログのいくつかのパラメーターを生成します。 @logeventの値は、クラスでデフォルト値として定義されています
4。LoginFogenerationのProcessManagerLogMessageを呼び出して、ログ内の他のパラメーターを入力します。この方法については後で説明します。
5.通常のビジネスコールを実行します
6.実行が成功した場合、ログマネージャーはログを実行します(ここで実行の成功のログのみを記録し、失敗した録音のログを定義することもできます)
@Around( "ManagerLogpoint()")ManagerLogpointの周りのパブリックオブジェクト(ProceedingJoinPoint JP)スロー可能{classターゲット= jp.getTarget()。getClass(); // logenable logenable logenable =(logenable)target.getannotation(logenable.class); if(logenable == null ||!logenable.logenable()){return jp.proceed(); } //デフォルト値logevent logeventclass =(logevent)target.getAnnotation(logevent.class)としてクラスのlogeventを取得します。メソッドメソッド= getInvokedMethod(jp); if(method == null){return jp.proceed(); } //メソッドlogevent logeventmethod = method.getAnnotation(logevent.class)でlogeventを取得します。 if(logeventmethod == null){return jp.proceed(); } string optevent = logeventmethod.event()。getevent(); string optmodel = logeventmethod.module()。getModule();文字列desc = logeventmethod.desc(); if(logeventclass!= null){//メソッドの値がデフォルト値の場合、グローバル値に置き換えます。 OptEvent = OptEvent.Equals(EventType.Default)? logeventclass.event()。getevent():optevent; optmodel = optmodel.equals(moduletype.default)? logeventclass.module()。getmodule():optmodel; } logadmmodel logbean = new logadmmodel(); logbean.setadmmodel(optmodel); logbean.setadmevent(optevent); logbean.setdesc(desc); logbean.setcreatedate(new date()); loginfogeneration.processingmanagerlogmessage(jp、logbean、method); Object Returnobj = jp.proceed(); if(optevent.equals(eventType.login)){// TODOログインしている場合、返品値に基づいて成功しているかどうかを判断する必要があります。成功した場合は、ログを追加します。ここでの判断は、(returnobj!= null){this.logmanager.deallog(logbean); }} else {this.logmanager.deallog(logbean); } return returnobj; } / ** *リクエスト方法を取得 * * @param jp * @return * / public method getInvokedMethod(joinpoint jp){//呼び出しメソッドリストclasslist = new ArrayList(); for(object obj:jp.getargs()){classlist.add(obj.getclass()); } class [] argscls =(class [])classlist.toarray(new class [0]); //呼び出されたメソッド名String methodname = jp.getSignature()。getName();メソッドメソッド= null; try {method = jp.getTarget()。getClass()。getMethod(methodName、argscls); } catch(nosuchmethodexception e){e.printstacktrace(); } return method; }}6.実際に上記のソリューションを適用するソリューション
ここでは、学生のビジネスをシミュレートし、上記の注釈を使用してそれらに適用し、ログをインターセプトします。
6.1。 ISTUDENTSERVICE
Business Interface Class、General Crudを実行します
public Interface istudentservice {void deletebyid(string id、string a); int Save(StudentModel StudentModel); void Update(StudentModel StudentModel); void querybyid(string id);}6.2。 StudentServiceImpl:
@logenable:@logeventを定義しているすべてのモジュールメソッド@logeven @logevenはlog @service @logenable // log intercevent @logevent(module = moduletype.student)Public classerviceimpl ISTudEntervice {@override @logevent(event = event = eventtype.delete_ dogedle、desc = "dec =" ded "ded" de dededle、eventtype.delete_singletexle deletebyid(@logkey(keyname = "id")string id、string a){system.out.printf(this.getclass() + "deletebyid id =" + id); } @Override @logevent(event = eventType.add、desc = "save record")// log識別子public int save(studentmodel sustentmodel){system.out.printf() + "save =" + json.tojsonstring(sustentmodel));返品1; } @Override @logevent(event = eventType.update、desc = "update record")// log識別子public void update(studentmodel sustentmodel){system.out.printf() + "save update =" + json.tojsonstring(dustentmodel)); } //ログ識別子@Override public void querybyid(string id){system.out.printf(this.getClass() + "querybyid id =" + id); }}テストクラスを実行し、次の情報を印刷して、ログアノテーション構成が有効になっていることを示します。
ログをデータベースに保存すると、ログコンテンツは次のとおりです。
{"admevent": "4"、 "admmodel": "1"、 "admoptcontent": "{/" id/":/" 1/"}"、 "recreatedate":15257797338111、 "desc": "delete record"}7。コード
上記の詳細なコードについては、以下を参照してください
githubコード、タグV0.21を使用してみてください、マスターを使用しないでください。マスターコードが変更されないことを保証できないため