幼儿饰品瑜伽美体用品微软
投稿投诉
微软创意
爱情通信
用品婚姻
爱好看病
美体软件
影音星座
瑜伽周边
星座办公
饰品塑形
搞笑减肥
幼儿两性
智家潮品

自定义注解妙用,一行代码搞定用户操作日志记录,你学会了吗?

  1。简介
  我在使用spring完成项目的时候需要完成记录日志,我开始以为Spring的AOP功能,就可以轻松解决,半个小时都不用,可是经过一番了解过后,发现一般的日志记录,只能记录一些简单的操作,例如表名、表名称等记录不到。
  这个时侯就用到了自定义注解,把想要记录的内容放在注解中,通过切入点来获取到注解参数,然后将参数插入数据库记录2。SpringAOP
  对于SpringAop的基本介绍大家可以看看:
  https:blog。csdn。netyjt520557articledetails84833508
  这里是为了方便大家理解如何实现给大家解释一下2。1。关于SpringAOP的一些术语切面(Aspect):在SpringAOP中,切面可以使用通用类或者在普通类中以Aspect注解(AspectJ风格)来实现连接点(Joinpoint):在SpringAOP中一个连接点代表一个方法的执行通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括around、before和after等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链切入点(Pointcut):定义出一个或一组方法,当执行这些方法时可产生通知,Spring缺省使用AspectJ切入点语法。通知类型前置通知(Before):在某连接点(joinpoint)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)返回后通知(AfterReturning):在某连接点(joinpoint)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回抛出异常后通知(AfterThrowing):方法抛出异常退出时执行的通知后通知(After):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)环绕通知(Around):包围一个连接点(joinpoint)的通知,如方法调用。这是最强大的一种通知类型,环绕通知可以在方法调用前后完成自定义的行为,它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行2。2。SpringAOP配置有两种风格:XML风格采用声明形式实现SpringAOPAspectJ风格采用注解形式实现SpringAOP3。首先自定义注解
  定义一个日志描述和一个表名这里根据需要自定义注解packagecom。ywj。log;importjava。lang。annotation。;ClassNameCrmlogAOPahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a记录自定义注解类Target({ElementType。PARAMETER,ElementType。METHOD})Retention(RetentionPolicy。RUNTIME)DocumentedpublicinterfaceSystemCrmlog{ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a描述对于什么表格进行了什么操作Stringdescription()default;操作了的表名returnStringtableName()default;}3。1。定义切面类,从切入点获取注解信息保存到数据库
  对于一些可能碰到的问题我在方法的注释里都有解决办法,大家注意一下,这里我对于方法报错也有处理方法
  这里是对于切面类里使用到的两个类解释:
  AspectJ使用org。aspectj。lang。JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org。aspectj。lang。ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。我们先来了解一下这两个接口的主要方法:1)JoinPointjava。lang。Object〔〕getArgs():获取连接点方法运行时的入参列表;SignaturegetSignature():获取连接点的方法签名对象;java。lang。ObjectgetTarget():获取连接点所在的目标对象;java。lang。ObjectgetThis():获取代理对象本身;2)ProceedingJoinPoint
  ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:java。lang。Objectproceed()throwsjava。lang。Throwable:通过反射执行目标对象的连接点处的方法;java。lang。Objectproceed(java。lang。Object〔〕args)throwsjava。lang。Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。packagecom。ywj。log;importcom。fasterxml。jackson。databind。ObjectMapper;importcom。ywj。log。biz。SyslogBiz;importcom。ywj。log。dao。SyslogDao;importcom。ywj。login。biz。SysUserBiz;importcom。ywj。login。dao。SysUserDao;importcom。ywj。login。dao。SysrighDao;importorg。aspectj。lang。JoinPoint;importorg。aspectj。lang。annotation。;importorg。springframework。stereotype。Component;importorg。springframework。web。context。request。RequestAttributes;importorg。springframework。web。context。request。RequestContextHolder;importorg。springframework。web。context。request。ServletRequestAttributes;importjavax。servlet。http。HttpServletRequest;importjava。lang。reflect。Method;importjava。text。SimpleDateFormat;importjava。util。Arrays;importjava。util。Date;importjava。util。List;importjava。util。Map;ClassNameSystemLogAspectAuthorAdministratorDescribe定义切入面类AspectComponentpublicclassSystemLogAspect{注解Pointcut切入点定义出一个或一组方法,当执行这些方法时可产生通知指向你的切面类方法由于这里使用了自定义注解所以指向你的自定义注解Pointcut(annotation(com。ywj。log。SystemCrmlog))publicvoidcrmAspect(){}抛出异常后通知(AfterThrowing):方法抛出异常退出时执行的通知注意在这里不能使用ProceedingJoinPoint不然会报错ProceedingJoinPointisonlysupportedforaroundadvicethrowing注解为错误信息paramjoinPointparamexAfterThrowing(valuecrmAspect(),throwingex)publicvoidafterThrowingMethod(JoinPointjoinPoint,Exceptionex)throwsException{HttpServletRequesthttpServletRequestgetHttpServletRequest();获取管理员用户信息WebUtilwebUtilnewWebUtil();MapString,ObjectuserwebUtil。getUser(httpServletRequest);CrmLogMessagelognewCrmLogMessage();获取需要的信息StringcontextgetServiceMthodDescription(joinPoint);Stringusrname;Stringrolename;if(user!null){usrnameuser。get(usrname)。toString();rolenameuser。get(rolename)。toString();}管理员姓名log。setUserName(usrname);角色名log。setUserRole(rolename);ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a信息log。setContent(usrnamecontext);设置参数集合log。setRemarks(getServiceMthodParams(joinPoint));设置表名log。setTableName(getServiceMthodTableName(joinPoint));操作时间SimpleDateFormatsifnewSimpleDateFormat(yyyyMMddHH:mm:ss);log。setDateTime(sif。format(newDate()));设置ip地址log。setIp(httpServletRequest。getRemoteAddr());设置请求地址log。setRequestUrl(httpServletRequest。getRequestURI());执行结果log。setResult(执行失败);错误信息log。setExString(ex。getMessage());将数据保存到数据库SyslogDaosysLogDaonewSyslogDao();sysLogDao。addSyslog(log);}返回后通知(AfterReturning):在某连接点(joinpoint)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回方法执行完毕之后注意在这里不能使用ProceedingJoinPoint不然会报错ProceedingJoinPointisonlysupportedforaroundadvicecrmAspect()指向需要控制的方法returning注解返回值paramjoinPointparamreturnValue返回值throwsExceptionAfterReturning(valuecrmAspect(),returningreturnValue)publicvoiddoCrmLog(JoinPointjoinPoint,ObjectreturnValue)throwsException{HttpServletRequesthttpServletRequestgetHttpServletRequest();获取管理员用户信息WebUtilwebUtilnewWebUtil();MapString,ObjectuserwebUtil。getUser(httpServletRequest);CrmLogMessagelognewCrmLogMessage();StringcontextgetServiceMthodDescription(joinPoint);Stringusrname;Stringrolename;if(user!null){usrnameuser。get(usrname)。toString();rolenameuser。get(rolename)。toString();}管理员姓名log。setUserName(usrname);角色名log。setUserRole(rolename);ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a信息log。setContent(usrnamecontext);设置参数集合log。setRemarks(getServiceMthodParams(joinPoint));设置表名log。setTableName(getServiceMthodTableName(joinPoint));操作时间SimpleDateFormatsifnewSimpleDateFormat(yyyyMMddHH:mm:ss);log。setDateTime(sif。format(newDate()));设置ip地址log。setIp(httpServletRequest。getRemoteAddr());设置请求地址log。setRequestUrl(httpServletRequest。getRequestURI());if(returnValue!null){if(returnValueinstanceofList){Listls(List)returnValue;if(ls。size()0){log。setResult(执行成功);}else{log。setResult(执行成功);}}elseif(returnValueinstanceofBoolean){Booleanfalg(Boolean)returnValue;if(falg){log。setResult(执行成功);}else{log。setResult(执行失败);}}elseif(returnValueinstanceofInteger){Integeri(Integer)returnValue;if(i0){log。setResult(执行成功);}else{log。setResult(执行失败);}}else{log。setResult(执行成功);}}将数据保存到数据库SyslogDaosysLogDaonewSyslogDao();sysLogDao。addSyslog(log);}获取自定义注解里的ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a描述paramjoinPointreturn返回注解里面的ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a描述throwsExceptionprivateStringgetServiceMthodDescription(JoinPointjoinPoint)throwsException{类名StringtargetNamejoinPoint。getTarget()。getClass()。getName();方法名StringmethodNamejoinPoint。getSignature()。getName();参数Object〔〕argumentsjoinPoint。getArgs();通过反射获取示例对象ClasstargetClassClass。forName(targetName);通过实例对象方法数组Method〔〕methodstargetClass。getMethods();Stringdescription;for(Methodmethod:methods){判断方法名是不是一样if(method。getName()。equals(methodName)){对比参数数组的长度Class〔〕clazzsmethod。getParameterTypes();if(clazzs。lengtharguments。length){获取注解里的ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a信息descriptionmethod。getAnnotation(SystemCrmlog。class)。description();break;}}}returndescription;}获取自定义注解里的表名paramjoinPointreturn返回注解里的表名字throwsExceptionprivateStringgetServiceMthodTableName(JoinPointjoinPoint)throwsException{类名StringtargetNamejoinPoint。getTarget()。getClass()。getName();方法名StringmethodNamejoinPoint。getSignature()。getName();参数Object〔〕argumentsjoinPoint。getArgs();通过反射获取示例对象ClasstargetClassClass。forName(targetName);通过实例对象方法数组Method〔〕methodstargetClass。getMethods();表名StringtableName;for(Methodmethod:methods){判断方法名是不是一样if(method。getName()。equals(methodName)){对比参数数组的长度Class〔〕clazzsmethod。getParameterTypes();if(clazzs。lengtharguments。length){获取注解里的表名tableNamemethod。getAnnotation(SystemCrmlog。class)。tableName();break;}}}returntableName;}获取json格式的参数用于存储到数据库中paramjoinPointreturnthrowsExceptionprivateStringgetServiceMthodParams(JoinPointjoinPoint)throwsException{Object〔〕argumentsjoinPoint。getArgs();ObjectMapperomnewObjectMapper();returnom。writeValueAsString(arguments);}获取当前的request这里如果报空指针异常是因为单独使用spring获取request需要在配置文件里添加监听listenerlistenerclassorg。springframework。web。context。request。RequestContextListenerlistenerclasslistenerreturnpublicHttpServletRequestgetHttpServletRequest(){RequestAttributesraRequestContextHolder。getRequestAttributes();ServletRequestAttributessra(ServletRequestAttributes)ra;HttpServletRequestrequestsra。getRequest();returnrequest;}}
  每个切面传递的数据的都不一样,最终决定,获取切面的所有参数,转成json字符串,保存到数据库中。相关类:
  日志信息类packagecom。ywj。log;ClassNameCrmLogMessageAuthorAdministratorDescribe数据库ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a类publicclassCrmLogMessage{privateIntegerlogid;ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志aidprivateStringUserName;管理员姓名privateStringUserRole;管理员角色privateStringContent;ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a描述privateStringRemarks;参数集合privateStringTableName;表格名称privateStringDateTime;操作时间privateStringresultValue;返回值privateStringip;ip地址privateStringrequestUrl;请求地址privateStringresult;操作结果privateStringExString;错误信息publicCrmLogMessage(){}OverridepublicStringtoString(){returnCrmLogMessage{logidlogid,UserNameUserName,UserRoleUserRole,ContentContent,RemarksRemarks,TableNameTableName,DateTimeDateTime,resultValueresultValue,ipip,requestUrlrequestUrl,resultresult,ExStringExString};}publicCrmLogMessage(Integerlogid,StringuserName,StringuserRole,Stringcontent,Stringremarks,StringtableName,StringdateTime,StringresultValue,Stringip,StringrequestUrl,Stringresult,StringexString){this。logidlogid;UserNameuserName;UserRoleuserRole;Contentcontent;Remarksremarks;TableNametableName;DateTimedateTime;this。resultValueresultValue;this。ipip;this。requestUrlrequestUrl;this。resultresult;ExStringexString;}publicStringgetExString(){returnExString;}publicvoidsetExString(StringexString){ExStringexString;}publicIntegergetLogid(){returnlogid;}publicvoidsetLogid(Integerlogid){this。logidlogid;}publicStringgetUserName(){returnUserName;}publicvoidsetUserName(StringuserName){UserNameuserName;}publicStringgetUserRole(){returnUserRole;}publicvoidsetUserRole(StringuserRole){UserRoleuserRole;}publicStringgetContent(){returnContent;}publicvoidsetContent(Stringcontent){Contentcontent;}publicStringgetRemarks(){returnRemarks;}publicvoidsetRemarks(Stringremarks){Remarksremarks;}publicStringgetTableName(){returnTableName;}publicvoidsetTableName(StringtableName){TableNametableName;}publicStringgetDateTime(){returnDateTime;}publicvoidsetDateTime(StringdateTime){DateTimedateTime;}publicStringgetResultValue(){returnresultValue;}publicvoidsetResultValue(StringresultValue){this。resultValueresultValue;}publicStringgetIp(){returnip;}publicvoidsetIp(Stringip){this。ipip;}publicStringgetRequestUrl(){returnrequestUrl;}publicvoidsetRequestUrl(StringrequestUrl){this。requestUrlrequestUrl;}publicStringgetResult(){returnresult;}publicvoidsetResult(Stringresult){this。resultresult;}}
  用来获取登录用户信息的帮助类:packagecom。ywj。log;importcom。base。web。BaseAction;importjavax。servlet。http。HttpServletRequest;importjava。util。Map;ClassNameWebUtilAuthorAdministratorDescribeahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a帮助类用来获取session中的用户信息来存入数据库publicclassWebUtil{从session中获取到用户对象returnpublicMapString,ObjectgetUser(HttpServletRequestrequest){MapString,Objectattributenull;if(request!null){Objectuserrequest。getSession()。getAttribute(Constans。USERKEY);attribute(MapString,Object)user;}returnattribute;}}
  在你的springcontext。xml中配置!启动对AspectJ注解的支持!自动扫描包路径!你需要刚才的切面类的包路径context:componentscanbasepackagecom。ywj。log!你需要注解方法的包路径context:componentscanbasepackagecom。。。biz。impl
  然后在你需要记录的方法上加上注解SystemCrmlog(description进行了登录操作,tableNameConstans。USERTABLENAME)
  效果这里表名使用了常量类
  对于一些表的信息可以写一个常量类
  然后执行登录操作数据库记录为:

湾区翼龙总经理刘全胜的大手笔能从他漫长的生涯履历中得出答案今年的休赛期,要是问谁是最大的赢家,那非香港湾区翼龙莫属,休赛期一共引进了9名cba联赛球员,其中不缺乏有实力的球员,像刘传兴,朱松玮,刘晓宇,郑祺龙等,致使cba联赛球员严重……夜拍实力强的三星GalaxyZFlip35G,拥有多种高科技手机拥有如此多的功能,对于现在的人们来说,早已成为了出行必不可少的物件。而小巧精致的手机,不仅携带方便,还更显时尚,就像这款三星GalaxyZFlip35G折叠屏手机,不仅美观……只买对的不买贵的,3款保值率高的旧手机,性能强续航长很多朋友说自己想买新机,但是预算差点又不想等怎么办,有没有其他的推荐呢,学长汇总了近两年保值率高,性能强续航也还不错的手机,他们不管是一手还是二手价,整体性价比都很高,一共三款……慈世平希望儿子代表菲律宾国家队比赛6月28日,东亚超级联赛分组抽签仪式在菲律宾马尼拉城堡香格里拉大酒店举行,前NBA总冠军、东超大使慈世平(曾用名:罗恩阿泰斯特)出席了仪式。在谈及自己和菲律宾的纽带时,4……武磊要代表日本队参加世界杯?西班牙媒体主动曝出,日媒立即回应最近西班牙媒体在报道世界杯相关信息的时候误将武磊报成日本球员,而且他还将代表日本队参加世界杯。这个消息被曝出以后引来了不少球迷的关注,西班牙媒体犯的这个错误实在是太不应该了,如……爱打山歌的爷爷头条创作挑战赛今天是2022年10月20日,天气多云,气温9到21。早上做核酸的时候,有零星的雨点,但一直也没有下雨。到了下午,天空稍微有点儿放晴,天还是阴沉沉的,还有一……你家孩子有没有这些ampampquot怪ampampquot儿童教育家蒙台梭利指出,儿童心理有一股无法抑制的动力,驱使他对自己感兴趣的事物产生尝试或学习的狂热,然后用一种惊人的方式自然而然的吸收,而当一种热情耗尽之后,另一种热情就会随之……原神逃逸电子成就获得攻略2022原神逃逸电子成就获得方法2022,原神游戏中有很多的玩法,其中很多人在游戏中不知道逃逸电子成就应该怎么去获得,下面跟着小编一起来看看吧,希望此文章能帮到你。原神逃逸电子成……在座的都是天生傲骨,玩不过一堆纸也太没意思了吧?想完成一件重要的事,最关键的环节不是什么设立远大目标、学习高效方法或者坚定自身意志,而是把这件事放在一个无可辩驳的最高优先级上。而其他所有事,不管听起来多么正确合理、多么理所应……小米12配置怎么样,是否值得入手?就我个人而言,小米12这款手机是小米有在销售的众多机型当中,一款非常不错的小屏旗舰手机了。小米12这款手机的尺寸为152。7mm69。9mm8。16mm,重量为180克。因为有……官宣品牌挚友润百颜品牌化战略进一步落地近日,玻尿酸科技护肤品牌润百颜引起了网友们的关注。润百颜官宣年轻演员李昀锐成为品牌挚友。这同时也昭示着润百颜品牌化战略的进一步落地。作为全球玻尿酸领导者知名生物科技公司华……北信源智慧党建安全平台,赋能党建工作安全高效信息化时代,智慧党建高需求凸显当前,我国互联网普及率已达到53。2,超过全球平均水平3。1。随着信息技术的迅猛发展和网民规模的不断扩大,互联网、大数据的运用已经由经济拓展……
34射进1球!曼联绝杀鱼腩滕哈格也有玄学45万欧门将征服梦剧10月14日凌晨,欧联杯小组赛第4轮拉开战幕,英超红魔曼联主场10小胜副班长奥莫尼亚,麦克托米奈替补出场在伤停补时第3分钟完成读秒绝杀。4轮过后,曼联3胜1负排名积分榜次席,再……华为Mate40Pro最新价格确认,价格下调1200元,高端因为一些众所周知的原因,华为遭受到了好几轮的限制,其中受影响最大的就是华为的海思芯片部门,因为海思部门现在是只能设计芯片,而不能制造芯片,因为此前给它代工的台积电,没办法再继续……药物性肝炎,你看看有多严重药物性肝炎指的是由于药物或者以及药物的代谢产物引起来的肝脏损害,可以发生在以往没有肝脏病史的健康患者当中,也有可能会发生在本来就有严重疾病的患者,在使用某些药物后会发生程度不同……南通六建破产重整启示录(四)为何产值492亿的庞然大物会破产恒大等暴雷房企还没见怎么着,为何建筑业的头部企业南通六建说倒就倒?2021年产值还有492亿元的南通六建,为何如此弱不禁风?究其根由,还在于南通六建的大而不强,其中建筑企业的挂……安东尼被换下很正常6686体育继续炫技可能会被铲飞09月06日讯,在曼联31战胜阿森纳的比赛中,安东尼首秀完成进球,内维尔在6686体育节目中表示安东尼如果没有被换下去继续在场上炫技,很有可能会被对方后卫铲飞。内维尔说道……涌入60万玩家后,逆水寒抢人大战升级,两大集团联手补贴200在网络游戏中,以帮派和联盟为单位的大型野外对抗,以及奖励非常丰厚的PVP赛事,一直都是最容易让所有玩家热血沸腾的玩法。在不少国产游戏,受制于各种原因,无法在游戏中植入大型……精致生活从Vivo开始,vivoX80Pro才是学生党的最优如今正值开学季,很多毕业生或者新晋大学生都会张罗着为自己准备一款手机,性能配置的优势、颜值至上已经成为当代年轻人的择机标准。而更具有决定性的优势则是vivoX80Pro相对于其……齐鲁女子凌壮志,敢叫日月换新天出生于烟台的女航天员王亚平刚刚从太空归来,连同她为女儿摘的小星星。这边海阳的王思雨就登上了世界女篮比赛的大舞台。一次匪夷所思的抢断,和二次精准的罚球,杀死了比赛。我们女篮赢了。……华为发布全新旗舰平板MatePadPro?媲美苹果iPadP多屏同色功能真的太顶了,想想笔记本电脑、手机和平板产品之间多屏协同,无论是LCD屏幕、HarmonyOS系统还是Windows系统,用户都能看到更加统一且准确的颜色,搞设计的人……重温经典赛事之2021女排世联赛顺口溜中韩之战3:1(一)中韩交锋战鼓鸣,比分胶着拼得凶。有惊无险三比一,视觉盛宴开门红。(二)奥运赛前大练兵,磨合队伍练硬功。以老带新里米尼,知……娱乐圈4位清流,无绯闻不炒作,她们的经历,个个值得称赞随着娱乐圈中的一些潜规则被曝光,很多人看到了这个圈子的复杂性,在这个鱼龙混杂的大染缸中,多少女演员因为禁不住诱惑而误入歧途。不过也不是所有人都把名和利放在第一位的,还是有……脾胃不好的孩子,容易出现这些现象,快速检查您的孩子是否有孩子的健康是家长们担心的一个重要事情。每一位父母都希望自己的孩子健健康康,快乐地成长现实不尽如人意,很多孩子身体不好。例如,我在幼儿园就职时,小小班里都是2岁半到未……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网