요구 사항 배경
최근 프로젝트에서 프로젝트가 기본적으로 완료되면 고객은 모든 비즈니스 운영의 로그를 데이터베이스에 기록하고 로그에서 일부 주요 비즈니스 정보 (예 : 거래 주문 번호)를 추출 할 것을 제안했습니다.
건설 기간을 보장하기 위해 정보를 검토 한 후 AOP + 사용자 정의 주석을 사용 하여이 요구 사항을 완료하기로 결정했습니다.
준비
사용자 정의 주석에 의존 해야하는 JAR 패키지에는 SpecialJrt-XXX.jar, SagneWeaver-xxx.jar가 포함되며 XXX는 버전 번호를 나타냅니다.
맞춤형 주석
로그 관련 컨텐츠를 저장하기 위해 프로젝트에서 별도의 로그 패키지가 생성됩니다.
**. common.log.annotation // 사용자 정의 주석 저장 위치 **. common.log.aop // aop 도구 저장 위치
주석 패키지에서 새 사용자 정의 주석 클래스를 만듭니다.
package **. common.log.annotation; import java.lang.annotation.elementtype; import java.lang.annotation.retention; import java.lang.annotation.retentionpolicy; import java.lang.annotation.target; @target ({elementtype.method})@retention (retention publate) xxxoperateLog { / *** 작동 유형 설명* @return* / String OperateTypedEsc () 기본값 ""; / *** 작동 유형* @return*/ Long OperateType () 기본값 -1; / *** 모듈 인코딩* @return*/ String MouseCode () 기본 "M30"; / *** 모듈 이름* @return*/ String MouseName () 기본 "XX Module"; / *** 비즈니스 유형* @return*/ String Busstype () 기본값 ""; / *** 비즈니스 유형 설명* @return*/ String BusstypeDesc () 기본값 "";}AOP 패키지 아래에서 새로운 xxxoperateLogaop을 만듭니다
package **. common.log.aop; import **; // acponentpublic class xxxoperatelogaop {@autowired systemlogservice systemlogservice; httpservletrequest request = null; logger logger = loggerfactory.getLogger (xxxoperateLogaop.class); ThreadLocal <long> time = new ThreadLocal <long> (); // 비즈니스 프로세스 감사 로그를 위해 공개 정적으로 호출하는 데 사용되는 작동 로그를 생성하는 데 사용되는 고유 ID 스레드 로컬 <string> tag = new ThreadLocal <string> (); // AOP 진입 점을 선언하면 XXXOPERATELOG를 사용하는 모든 메소드가 @PointCut ( " @annotation (**. common.log.annotation.xxxoperateLog)") public void log () {System.out.println ( "I am Entry Point"); } / *** 모든 장소에서 @log* @param joinpoint* / @before ( "log ()") public void perectexec (joinpoint joinpoint) {time.set (System.CurrentTimeMillis ()); 정보 (joinpoint); // 로그 레코드의 고유 식별 번호 설정 tag.set (uuid.randomuuid (). tostring ()); request = ((servletRequestAttributes) requestContexTholder.getRequestAttributes (). getRequest (); } @after ( "log ()") public void attexec (joinpoint joinpoint) {methodSignature ms = (methodSignature) joinpoint.getSignature (); 메소드 메소드 = ms.getMethod (); logger.debug ( "tag as as" + tag.get () + "method" + method.getname () + "run run soception" + (System.CurrentTimeMillis () - time.get ()) + "ms"); } // 대상 방법을 실행하는 과정 에서이 메소드가 실행되며 여기에서 @around ( "log ()") 공개 객체 주위에 공개 객체 (proceedingjoinpoint pjp) 던지기 가능 {object ret = pjp.proceed (); {object [] orgs = pjp.getargs (); SystemLog valuereturn = null; for (int i = 0; i <orgs.length; i ++) {if (orgs [i] systemlog) {valuereturn = (SystemLog) orgs [i]; }} if (valuereturn == null) {valuereturn = new SystemLog (); } if (valuereturn! = null && request! = null) {MethodSignature ms = (MethodSignature) pjp.getSignature (); 메소드 메소드 = ms.getMethod (); // 주석 XXXOPERATELOG LOG = Method.GetAntation (xxxoperateLog.class)의 작동 로그 정보를 가져옵니다. 문자열 businesstype = log.busstype (); 문자열 businessdesc = log.busstypedesc (); Hashmap requestmap = servletutils.getParameterstohashmap (요청); // (businesstype.equals ( "")) {개체 objbusinesstype = requestMap.get ( "business_type"); businesstype = objbusinesstype == null? "": objbusinesstype.toString (); } // 실행 결과에 대한 신청서에서 비즈니스 유형을 찾았습니다. 객체 apply = request.getAttribute ( "apply"); if (apply! = null) {jsonobject obj = jsonfactory.tojsonabstractentity (적용); if (obj! = null) {valuereturn.setotherdesc ( "적용 숫자 :"+obj.getstring ( "apply_no")); if (businesstype.equals ( "")) {businesstype = obj.getString ( "business_type"); }}} // 메소드의 실행 프로세스 매개 변수에서 비즈니스 유형을 찾는 경우 (일반적으로 설정) if (businessType.equals ( "")) {businessType = (string) request.getAttribute ( "business_type"); BusinessType = businessType == null? "": BusinessType; } if (! businessType.equals ( "") && businessDesc.equals ( "")) {businessDesc = xxxsysconstant.business_type.getName (businessType); } valuereturn.setBusstype (xxxsysconstant.business_type.getNumber (businessType)); Valuereturn.SetBusstypedesc (BusinessDesc); valuereturn.setMoudLecode (log.moudleCode ()); valuereturn.setMoudLename (log.MoudLename ()); valuereturn.setoperateresult (xxxsysconstant.yesorno.yes); valuereturn.setoperateType (log.operateType ()); valuereturn.setInputUserId ((((userconText) wecutils.getSessionAttribute "). getSysUser (). getId ()); Valuereturn.setoperateTypedesc (log.operateTypedesc ()); valuereturn.setRequestip (getRemoteHost (요청)); valuereturn.setRequestUrl (request.getRequesturi ()); valuereturn.setserverip (request.getLocalAddr ()); valuereturn.setuids (tag.get ()); // 작동 로그를 저장 SystemLogService.SavesyStemLog (ValuerEturn); } else {logger.info ( "로그 정보를 기록하지 않음"); } // 작동 결과 저장} catch (예외 e) {e.printstacktrace (); } 반환 리턴; } // 레코드 예외 로그 @AfterThrowing (pointCut = "log ()", Throwing = "e") public void doafterThrowing (joinpoint joinpoint, trashable e) {try {info (joinpoint); Object [] orgs = joinpoint.getargs (); SystemLog valuereturn = null; for (int i = 0; i <orgs.length; i ++) {if (orgs [i] systemlog) {valuereturn = (SystemLog) orgs [i]; }} if (valuereturn == null) {valuereturn = new SystemLog (); } if (valuereturn! = null && request! = null) {MethodSignature ms = (MethodSignature) joinpoint.getSignature (); 메소드 메소드 = ms.getMethod (); xxxoperateLog log = method.getAnnotation (xxxoperateLog.class); 문자열 businesstype = log.busstype (); 문자열 businessdesc = log.busstypedesc (); if (businesstype.equals ( "")) {Object objbusinessType = servletutils.getParameterstoShashMap (request) .get ( "business_type"); businesstype = objbusinesstype == null? "": objbusinesstype.toString (); BusinessDesc = xxxsysconstant.business_type.getName (businessType); } valuereturn.setBusstype (xxxsysconstant.business_type.getNumber (businessType)); Valuereturn.SetBusstypedesc (BusinessDesc); valuereturn.setMoudLecode (log.moudleCode ()); valuereturn.setMoudLename (log.MoudLename ()); valuereturn.setoperateType (log.operateType ()); Valuereturn.setoperateTypedesc (log.operateTypedesc ()); valuereturn.setInputUserId ((((userconText) wecutils.getSessionAttribute "). getSysUser (). getId ()); valuereturn.setoperateresult (xxxssysconstant.yesorno.no); 문자열 errmes = e.getMessage (); if (errmes! = null && errmes.length ()> 800) {errmes = errmes.substring (0, 800); } valuereturn.seterRormessage (errmes); valuereturn.setRequestip (getRemoteHost (요청)); valuereturn.setRequestUrl (request.getRequesturi ()); valuereturn.setserverip (request.getLocalAddr ()); valuereturn.setuids (tag.get ()); SystemLogservice.savesystemlog (Valuereturn); } else {logger.info ( "로그 정보가 기록되지 않음"); }} catch (예외 e1) {e1.printstacktrace (); }} private void info (joinpoint joinpoint) { logger.debug("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Object[] OS = getargs (); "args :"); logger.debug ( "sourceloce :/t" + joinpoint.getSourcelocation ()); logger.debug("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 요청. IP = getRemoteaddr ();구성 파일 Spring-MVC.XML 수정하고 다음 구성을 추가하십시오.
<!-AOP 차단-> <aop : agage-autoproxy proxy-target-class = "true" /> <mvc : 주석 구동 /> <!-스프링 설명 범위를 정의합니다.-> <context : component-scan base-package = "**. common.log"> expression = "org.springframework.stereotyp.controller"/> </context : component-scan>
위 구성은 Spring-MVC.xml 또는 Spring-Context.xml의 동일한 XML 파일에 배치해야합니다. 그렇지 않으면 효과가 없을 수도 있으며 그 이유는 아직 발견되지 않았습니다.
주석 사용
@xxxoperateLog (busstype = xxxsysconstant.business_type.yyy, busstypedesc = "비즈니스 유형 설명", operateType = xxxsysconstant.logoperateType.query, operateTeTypedEsc = "Operation Description") @RequestMapping (value = ", Queperyxexxexxexxexxexxexxexexect.query, operateType = xxxsysconstant.logoperatetype.query requestmethod.post) public void queryxxxxx4datagrid (httpservletrequest request, httpservletrepsonge arg1, 모델 모델, 작가 작가) { logger.info ( "============================================================================================= {logger.info ( "========================= httpservletresponse arg1, 모델 모델, 작가 작가) {logger.info ("================================================= {logger.info ( "======================================================= 모델 모델, 작가 작성자) {logger.info ("==================== httpservletronsponse arg1, 모델 모델, Writer Writer) { logger.info ( "========================== httpservletResponse arg1, 모델 모델, 작가 작가) {logger.info ("========================= logger.info ( "==================== httpservletResponse arg1, 모델 모델,위의 SpringMVC 사용자 정의 주석, AOP를 사용하여 로깅을 실현하는 방법은 내가 공유하는 모든 컨텐츠입니다. 나는 당신이 당신에게 참조를 줄 수 있기를 바랍니다. 그리고 당신이 wulin.com을 더 지원할 수 있기를 바랍니다.