1. 개요
일반 시스템에서는 시스템에 로그인, 사용자 추가, 사용자 삭제 등과 같은 중요한 작업을 수행 할 때 이러한 동작을 지속해야합니다. 이 기사에서는 Spring AOP 및 Java의 사용자 정의 주석을 통해 로그 삽입을 구현합니다. 이 솔루션은 원래 비즈니스에 대한 침입이 적고 실현에 더 유연합니다.
2. 로그의 관련 클래스 정의
로그인은 기능 모듈과 작동 유형의 두 클래스로 추출합니다.
열거 클래스를 사용하여 학생 및 사용자 모듈과 같은 함수 모듈 유형 모듈 유형을 정의합니다.
public enum moduletype {default ( "1"), // default value student ( "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"), 로그인 ( "10", "로그인"), login_out ( "11", "login_out"); private eventType (문자열 색인, 문자열 이름) {this.name = name; this.event = index; } 개인 문자열 이벤트; 개인 문자열 이름; public String getEvent () {return this.event; } public String getName () {return name; }}3. 로그 관련 주석을 정의하십시오
3.1. @Logenable
여기서 우리는 로그의 스위치 수량을 정의합니다. 클래스 에서이 값이 참을 때만이 클래스의 로그 함수가 활성화됩니다.
@documented @rendent (rendentionpolicy.runtime) @target ({elementtype.type}) public @interface logenable { / ** * 클래스 아래의 logevent가 활성화됩니다. 그렇지 않으면 * @return * / boolean logenable () default true;}3.2. @logevent
여기에서 로그의 정의. 이 주석이 클래스에 주석이 달린 경우이 매개 변수는 클래스의 모든 방법의 기본값으로 사용됩니다. 주석이 메소드에있는 경우이 방법에 대해서만 작동합니다.
@documented@retention (retentionpolicy.runtime) @target ({java.lang.annotation.elementtype.method, elementtype.type}) public @interface logevent {moduletype module () default moduletype.default; // 로그가 속한 모듈은 eventType event () default eventtype.default; // 로그 이벤트 유형 문자열 desc () default ""; // 설명 정보}3.3. @Logkey
이 주석이 메소드에 있으면 전체 메소드의 매개 변수가 로그인 JSON 형식에 저장됩니다. 이 주석이 메소드와 클래스 모두에 주석이 달라지면 메소드의 주석은 클래스의 값을 덮어 씁니다.
@TARGET ({ElementType.field, ElementType.parameter})@resentention(retentionpolicy.runtime)@documentedpublic @interface logkey {String keyname () 기본값 ""; // Key Boolean isuserid ()의 이름의 이름은 거짓일 거짓; //이 필드 가이 작업의 사용자이든 여부에 관계없이 여기에 Boolean Islog () Default True가 생략됩니다. // 로그에 추가되었는지}4. 로그 처리 클래스를 정의하십시오
4.1. logadmmodel
로그 정보를 보유하는 클래스를 정의하십시오
공개 클래스 logadmmodel {private long id; 개인 문자열 userID; // 사용자 개인 문자열 사용자 이름을 작동합니다. 개인 문자열 Admmodel; // 모듈 개인 문자열 Admevent; // 작동 날짜가 생성 된 운영; // 작동 콘텐츠 개인 문자열 AdmoPtContent; // 작동 콘텐츠 개인 문자열 desc; // 비고 세트/생략}}4.2. Ilogmanager
로그 처리를 위해 인터페이스 클래스 ILOGMANAGER를 정의하십시오
데이터베이스에 로그를 저장하거나 Redis, MQ 등이있는 경우 Middleware Open에 로그를 보낼 수 있습니다. 각 로그 처리 클래스는이 인터페이스의 구현 클래스입니다.
공개 인터페이스 ilogmanager { / *** 로그 처리 모듈* @param paramlogadmbean* / void deallog (logadmmodel paramlogadmbean);}4.3. dblogmanager
Ilogmanager 구현 클래스로 로그를 저장합니다. 여기에서 스토리지 만 시뮬레이션했습니다
@ServicePublic Class DBlogManager는 ilogmanager {@override public void deallog (logadmmodel paramlogadmbean) {system.out.println ( "데이터베이스에 로그를 저장하면 로그 컨텐츠는 다음과 같습니다." + json.tojsonstring (paramlogadmbean)); }}5. AOP 구성
5.1. logaSpect AOP 클래스를 정의합니다
이 클래스에 @aspect에 주석을 달 수 있습니다
@PointCut을 사용하여 패키지 및 클래스 메소드를 정의하여 가로 채기
우리는 @around를 사용하여 메소드를 정의합니다
@component @public class logaSpect {@autowired private loginfogeneration loginfogeneration; @autowired private ilogmanager logmanager; @PointCut ( "execution (*com.hry.spring.mvc.aop.log.service ..*.*(..))") public void mangeringlogpoint () {} @Around ( "managerLogpoint ()") 공개 객체 주변 ManagerLogpoint (ProceedingJoinPoint JP) Throws Throwable {…. }} 주변 ManagerLogpoint : 주요 방법의 주요 비즈니스 프로세스
1. 가로 채기 방법의 클래스에 @logenable에 의해 주석이 달라 지는지 확인하십시오. 그렇다면 로그 로직이 따르면 일반 논리가 실행됩니다.
2. 인터셉트 메소드가 @logevent인지 확인하십시오. 그렇다면 로그 로직이 따르면 일반 논리가 실행됩니다.
3. 획득 방법을 기반으로 @logevent의 중간 값을 얻고 로그의 일부 매개 변수를 생성합니다. @logevent의 값은 클래스에서 기본값으로 정의됩니다.
4. 로그의 다른 매개 변수를 채우려면 loginfogenteration의 ProcessManagerLogMessage를 호출하십시오. 나중에이 방법에 대해 이야기하겠습니다.
5. 정상적인 비즈니스 전화를 수행하십시오
6. 실행이 성공하면 LogManager가 로그를 실행합니다 (여기서 성공적인 실행 로그 만 기록하고 녹음 실패의 로그를 정의 할 수도 있음).
@Around ( "managerLogpoint ()") 공개 객체 주변 ManagerLogpoint (proceedingjoinpoint jp) 던지기 가능 {class target = jp.getTarget (). getClass (); // logenable logenable logenable = (logenable) target.getAnnotation (logenable.class)을 가져옵니다. if (logenable == null ||! logenable.logenable ()) {return jp.proceed (); } // 클래스의 logevent를 기본값 logeventclass = (logevent) target.getAntation (logevent.class)으로 가져옵니다. 메소드 메소드 = getInvokedMethod (jp); if (method == null) {return jp.proceed (); } // 메소드 Logevent LogeventMethod = method.getAntation (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 (새 날짜 ()); loginfogeneration.processingmanagerLogMessage (jp, logbean, method); Object ReturnObj = jp.proceed (); if (optevent.equals (eventType.login)) {// 로그인 된 경우 반환 값에 따라 성공 여부를 판단해야합니다. 성공하면 로그를 추가하십시오. 여기의 판단은 if (returnobj! = null) {this.logmanager.deallog (logbean); }} else {this.logmanager.deallog (logbean); } return returnObj; } / ** * 요청 메소드 가져 오기 * * @param jp * @return * / public method getInvokedMethod (joinpoint jp) {// 호출 메소드 목록 클래스리스트 = 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; {method = jp.getTarget (). getClass (). getMethod (MethodName, Argscls); } catch (nosuchmethodexception e) {e.printstacktrace (); } 반환 방법; }}6. 위의 솔루션을 실제로 적용하는 솔루션
여기서 우리는 학생들의 사업을 시뮬레이션하고 위의 주석을 사용하여 그들에게 적용하고 로그를 가로 채립니다.
6.1. istudentservice
비즈니스 인터페이스 클래스, General Crud를 실행하십시오
public interface istudentservice {void deletebyid (문자열 id, 문자열 a); int save (StudentModel StudentModel); 무효 업데이트 (StudentModel StudentModel); void QueryById (String ID);}6.2. weentlyerviceimpl :
@Logenable : @logevent는 시작 로그 인터셉트 클래스에서 모든 모듈 메소드를 정의합니다. @logeven에 대한 다른 정보는 로그를 정의합니다. @service @logenable // 시작 로그 인터셉트 @logevent (module = moduletype.student) public class elidenterviceimpl은 istudentservice {@override @logevent (event = eventtype.delete_single, desc = "deleet void void deletebyid (@logkey (@logkey)"id and System.out.printf (this.getClass () + "deleteById id =" + id); } @override @logevent (event = eventtype.add, desc = "레코드 저장") // 로그 식별자 추가 공개 int save (studentmodel wichael save) {system.out.printf (this.getCrass () + "save =" + json.tojsonstring (StudentModel)); 반환 1; } @override @logevent (event = eventtype.update, desc = "업데이트 레코드") // 로그 식별자 공개 void update (windentmodel stutent -model) {system.out.printf (this.getCrass () + "update =" + json.tojsonstring (StudentModel)); } // 로그 식별자 없음 @override public void QueryById (String id) {System.out.printf (this.getClass () + "QueryById id =" + id); }}테스트 클래스를 실행하고 다음 정보를 인쇄하여 로그 주석 구성이 활성화되어 있음을 나타냅니다.
로그를 데이터베이스에 저장하면 로그 컨텐츠는 다음과 같습니다.
{ "Admevent": "4", "Admmodel": "1", "AdmoptContent": "{/"id/":/"1/"}", "생성물": 1525779738111, "desc": "삭제"}7. 코드
위의 자세한 코드는 아래를 참조하십시오
GitHub 코드, Tag v0.21을 사용해보십시오. 마스터를 사용하지 마십시오. 마스터 코드가 변경되지 않도록 보장 할 수 없기 때문입니다.