游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

一个注解搞定,记录项目日志

  最近正在录制TienChin项目视频采用SpringBootVue3技术栈,里边会涉及到各种好玩的技术,小伙伴们来和我一起做一个完成率超90的项目。
  前段时间做了一个支线任务,现在还是回到我们的主线上面来,继续完成TienChin项目。
  小伙伴们知道我最近在录制TienChin项目视频教程,这是一个基于RuoYiVue脚手架的项目,用过这个脚手架的小伙伴可能知道,这个脚手架有一个功能,就是如果你需要记录下来一个接口的操作信息,那么只需要在Controller接口中加上一个Log注解即可,非常方便,最终记录到数据库中的日志类似下面这样:
  可能有小伙伴要吐槽了,这不该记录到Elasticsearch中吗?上ELK啊!怎么说呢,如果你会将日志存入数据库,那么将来存Elasticsearch其实非常Easy,结合我之前录制的Es视频,我相信这个问题你能自己搞定。
  今天我们主要来分析一下这个脚手架中Log注解的玩法。1。日志表设计
  先来看看日志表的设计。CREATETABLEsysoperlog(operidbigint(20)NOTNULLAUTOINCREMENTCOMMENTahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a主键,titlevarchar(50)COLLATEutf8mb4unicodeciDEFAULTCOMMENT模块标题,businesstypeint(2)DEFAULT0COMMENT业务类型(0其它1新增2修改3删除),methodvarchar(100)COLLATEutf8mb4unicodeciDEFAULTCOMMENT方法名称,requestmethodvarchar(10)COLLATEutf8mb4unicodeciDEFAULTCOMMENT请求方式,operatortypeint(1)DEFAULT0COMMENT操作类别(0其它1后台用户2手机端用户),opernamevarchar(50)COLLATEutf8mb4unicodeciDEFAULTCOMMENT操作人员,deptnamevarchar(50)COLLATEutf8mb4unicodeciDEFAULTCOMMENT部门名称,operurlvarchar(255)COLLATEutf8mb4unicodeciDEFAULTCOMMENT请求URL,operipvarchar(128)COLLATEutf8mb4unicodeciDEFAULTCOMMENT主机地址,operlocationvarchar(255)COLLATEutf8mb4unicodeciDEFAULTCOMMENT操作地点,operparamvarchar(2000)COLLATEutf8mb4unicodeciDEFAULTCOMMENT请求参数,jsonresultvarchar(2000)COLLATEutf8mb4unicodeciDEFAULTCOMMENT返回参数,statusint(1)DEFAULT0COMMENT操作状态(0正常1异常),errormsgvarchar(2000)COLLATEutf8mb4unicodeciDEFAULTCOMMENT错误消息,opertimedatetimeDEFAULTNULLCOMMENT操作时间,PRIMARYKEY(operid))ENGINEInnoDBAUTOINCREMENT280DEFAULTCHARSETutf8mb4COLLATEutf8mb4unicodeciCOMMENT操作ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a记录;
  这里各个字段的含义我来解释下:operid:这是日志主键,自增的。title:这个标题,一般就是用来说明这个操作是干嘛的,例如删除一个用户、添加一条线索等待。businesstype:这个是指业务类型,一般来说有:添加、修改、删除、导入、导出等等。method:执行的接口方法名称。requestmethod:这个是指请求的方法类型,如GET、POST、PUT、DELETE等。operatortype:这个是指操作类别,分为三种:后台用户、手机用户以及其他。opername:操作人员的名称。deptname:操作人员所属的部门。operurl:请求的URL地址。operip:请求的IP地址。operlocation:请求IP地址所属的区域。operparam:请求的参数。jsonresult:响应的JSON参数。status:操作的状态,成功还是失败。errormsg:如果是失败,失败的内容是什么。opertime:操作的时间。
  这里给出来的就这些字段,基本上满足项目需求了,如果不够的话,也可以自定添加即可。2。注解的定义
  再来看看Log注解的定义,该注解位于org。javaboy。tienchin。common。annotation。Log:Target({ElementType。PARAMETER,ElementType。METHOD})Retention(RetentionPolicy。RUNTIME)DocumentedpublicinterfaceLog{模块publicStringtitle()default;功能publicBusinessTypebusinessType()defaultBusinessType。OTHER;操作人类别publicOperatorTypeoperatorType()defaultOperatorType。MANAGE;是否保存请求的参数publicbooleanisSaveRequestData()defaulttrue;是否保存响应的参数publicbooleanisSaveResponseData()defaulttrue;}
  这个注解一共有五个属性,结合上面表的定义,五个属性含义很好理解,不多说。3。注解的解析
  经典搭配:自定义注解AOP切面。解析该注解的AOP切面是LogAspect,位于org。javaboy。tienchin。framework。aspectj。LogAspect:AspectComponentpublicclassLogAspect{privatestaticfinalLoggerlogLoggerFactory。getLogger(LogAspect。class);处理完请求后执行paramjoinPoint切点AfterReturning(pointcutannotation(controllerLog),returningjsonResult)publicvoiddoAfterReturning(JoinPointjoinPoint,LogcontrollerLog,ObjectjsonResult){handleLog(joinPoint,controllerLog,null,jsonResult);}拦截异常操作paramjoinPoint切点parame异常AfterThrowing(valueannotation(controllerLog),throwinge)publicvoiddoAfterThrowing(JoinPointjoinPoint,LogcontrollerLog,Exceptione){handleLog(joinPoint,controllerLog,e,null);}protectedvoidhandleLog(finalJoinPointjoinPoint,LogcontrollerLog,finalExceptione,ObjectjsonResult){try{获取当前的用户LoginUserloginUserSecurityUtils。getLoginUser();数据库ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志aSysOperLogoperLognewSysOperLog();operLog。setStatus(BusinessStatus。SUCCESS。ordinal());请求的地址StringipIpUtils。getIpAddr(ServletUtils。getRequest());operLog。setOperIp(ip);operLog。setOperUrl(ServletUtils。getRequest()。getRequestURI());if(loginUser!null){operLog。setOperName(loginUser。getUsername());}if(e!null){operLog。setStatus(BusinessStatus。FAIL。ordinal());operLog。setErrorMsg(StringUtils。substring(e。getMessage(),0,2000));}设置方法名称StringclassNamejoinPoint。getTarget()。getClass()。getName();StringmethodNamejoinPoint。getSignature()。getName();operLog。setMethod(className。methodName());设置请求方式operLog。setRequestMethod(ServletUtils。getRequest()。getMethod());处理设置注解上的参数getControllerMethodDescription(joinPoint,controllerLog,operLog,jsonResult);保存数据库AsyncManager。me()。execute(AsyncFactory。recordOper(operLog));}catch(Exceptionexp){记录本地异常ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志alog。error(前置通知异常);log。error(异常信息:{},exp。getMessage());exp。printStackTrace();}}获取注解中对方法的描述信息用于Controller层注解paramlogahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志aparamoperLog操作ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志athrowsExceptionpublicvoidgetControllerMethodDescription(JoinPointjoinPoint,Loglog,SysOperLogoperLog,ObjectjsonResult)throwsException{设置action动作operLog。setBusinessType(log。businessType()。ordinal());设置标题operLog。setTitle(log。title());设置操作人类别operLog。setOperatorType(log。operatorType()。ordinal());是否需要保存request,参数和值if(log。isSaveRequestData()){获取参数的信息,传入到数据库中。setRequestValue(joinPoint,operLog);}是否需要保存response,参数和值if(log。isSaveResponseData()StringUtils。isNotNull(jsonResult)){operLog。setJsonResult(StringUtils。substring(JSON。toJSONString(jsonResult),0,2000));}}获取请求的参数,放到log中paramoperLog操作ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志athrowsException异常privatevoidsetRequestValue(JoinPointjoinPoint,SysOperLogoperLog)throwsException{StringrequestMethodoperLog。getRequestMethod();if(HttpMethod。PUT。name()。equals(requestMethod)HttpMethod。POST。name()。equals(requestMethod)){StringparamsargsArrayToString(joinPoint。getArgs());operLog。setOperParam(StringUtils。substring(params,0,2000));}else{Maplt;?,?paramsMap(Maplt;?,?)ServletUtils。getRequest()。getAttribute(HandlerMapping。URITEMPLATEVARIABLESATTRIBUTE);operLog。setOperParam(StringUtils。substring(paramsMap。toString(),0,2000));}}参数拼装privateStringargsArrayToString(Object〔〕paramsArray){Stringparams;if(paramsArray!nullparamsArray。length0){for(Objecto:paramsArray){if(StringUtils。isNotNull(o)!isFilterObject(o)){try{ObjectjsonObjJSON。toJSON(o);paramsjsonObj。toString();}catch(Exceptione){}}}}returnparams。trim();}判断是否需要过滤的对象。paramo对象信息。return如果是需要过滤的对象,则返回true;否则返回false。publicbooleanisFilterObject(finalObjecto){Classlt;?clazzo。getClass();if(clazz。isArray()){returnclazz。getComponentType()。isAssignableFrom(MultipartFile。class);}elseif(Collection。class。isAssignableFrom(clazz)){Collectioncollection(Collection)o;for(Objectvalue:collection){returnvalueinstanceofMultipartFile;}}elseif(Map。class。isAssignableFrom(clazz)){Mapmap(Map)o;for(Objectvalue:map。entrySet()){Map。Entryentry(Map。Entry)value;returnentry。getValue()instanceofMultipartFile;}}returnoinstanceofMultipartFileoinstanceofHttpServletRequestoinstanceofHttpServletResponseoinstanceofBindingResult;}}
  大概跟小伙伴们捋一下这个切面的逻辑。首先定义了两种不同类型的通知:返回通知和异常通知,正常流程就是在返回通知中处理日志写入操作,但是如果系统不幸抛出异常,就在异常通知中处理日志写入操作(此时就多了一个异常对象)。日志数据保存在SysOperLog对象中,采集各种日志数据都是常规操作,不多说。当收集接口参数的时候,有两个需要注意的地方:1。如果请求类型是PUT或者POST,就直接从接口的参数中获取想要的数据,但是接口的参数中可能会存在一些并不需要记录的内容,例如HttpServletRequest、HttpServletResponse或者文件上传对象MultipartFile等,这些类型的内容是不需要记录到日志中的,这里通过一个isFilterObject方法完成了数据过滤操作;2。如果请求类型是GET或者DELETE,则请求参数就直接从请求对象提取了。为什么设计成这样呢?很明显,直接从请求对象中提取参数是最为方便的,一行代码就搞定,但是如果请求类型是PUT或者POST,就意味着请求参数是在请求体中,请求参数有可能是二进制数据(例如上传的文件),二进制数据就不好保存了,所以对于POST和PUT还是从接口参数中提取,然后过滤掉二进制数据即可。数据收集齐了,接下来就是往数据库中写入了。因为我们现在用的SpringMVC这一套是线程阻塞的,也就是得等到服务端都处理完毕之后,接口才会给客户端响应,而写日志是一个业务无关的操作,所以可以直接放在一个子线程中去完成。在RuoYiVue脚手架中,使用了JavaJUC中的ScheduledExecutorService去完成这个延时任务,AsyncManager。me()。execute方法实际上就是去执行一个延时任务,这个延时任务就是一个往数据库中写入一条记录。4。记录日志
  弄好之后,日志注解具体用法如下:Log(title参数管理,businessTypeBusinessType。EXPORT)PreAuthorize(ss。hasPermi(system:config:export))PostMapping(export)publicvoidexport(HttpServletResponseresponse,SysConfigconfig){ListSysConfiglistconfigService。selectConfigList(config);ExcelUtilSysConfigutilnewExcelUtilSysConfig(SysConfig。class);util。exportExcel(response,list,参数数据);}
  好啦,这就是整体操作,实际上看起来并不难,后面要是有空的话,我把这个日志整成一个ELK的,和小伙伴们一起探讨。
  我最近正在录制TienChin项目视频采用SpringBootVue3技术栈,里边会涉及到各种好玩的技术,小伙伴们来和我一起做一个完成率超90的项目。

大众捷达独立了,新车来袭,车标却被吐槽,车友比老款强目前捷达成为了大众旗下一个独立的子品牌,新的品牌亮相之后,相继的推出了捷达品牌旗下的三款全新的车型,分别是SUV车型VS5和VS7,另外还有一款家用轿车VA3。这三款车型均在上……他是坑爹的星二代,十五岁无证驾驶兼打人,十七岁轮奸醉酒女中国自古就有父是英雄儿好汉,虎父无犬子之说,然而现实生活中,却总有父是龙,儿是虫的真实存在。这些凭实力坑爹的人,如发生在娱乐圈,就会让人们津津乐道。2003年,张默痛打女……想让孩子在外貌定型之前越长越好看,送你3个小秘诀,请收好在孩子呱呱坠地之后,新手爸妈们最迫切关注的除了孩子的身体健康之外,还有孩子的颜值。毕竟在现代这个看脸的社会,一个人有了高颜值,就相当于有了很大的优势。不过,很多人却发现了……有生之年系列!半瓶神仙醋出品武侠新作正式公布就在今天,游戏制作人半瓶神仙醋向大家宣布了一条好消息新作《大侠立志传》的宣传片正式和大家见面了!这部作品和12年前的《金2、3》系列不同,它是立足于全新的IP之上开发的。当然,……不为速度而妥协的艺术品帕加尼Zonda诞生20周年Zonda20周年庆典在香港举行帕加尼品牌创始人荷拉齐奥帕加尼先生(HoracioPagani)参加庆典。历史距离帕加尼Zonda,C12第一次亮相公众已经过……B级车一大黑马,满油一次跑940公里提速7。1S,四十年口碑转载自百家号作者:笑侃天下名车导读:B级车一大黑马,满油一次跑940公里提速7。1S,四十年口碑好评如潮!B级车作为中高级经济实力车友的首选,极为苛刻的品质,性能以……选一辆车择一种生活还记得你的第一辆车么?在购车的时候,你最看重什么?日常出行,上下班代步,考虑更多的是油耗;热衷自驾,经常采购,也会在意空间;家有宝贝,居家常用,安全性能……最可惜的大众车,比速腾高尔夫都更适合家用,无奈欣赏的人不多如果问在国内的合资品牌中,哪个品牌最受欢迎,那么答案毫无疑问便是大众。在国内的汽车工业刚刚起步时,大众汽车就开始进入中国市场,与自主厂商建立了合资关系,而且像桑塔纳、捷达等非常……降准了!跟房价有什么关系?说通俗一点,降准就是让各大银行,把仓库里面的备用金拿出一部分,用来借给别人,以此促进市场的消费。但是在房地产行业里面,受影响的只是房子的数量,而不是房子的价格,自上个月降……禁摩限电已实施,为何不直接禁止生产摩托车?青岛网友天真现在汽车是一种很常见的交通工具,我们大家都知道汽车给我们的出行带来了很大的便利,但是随着汽车数量的不断增加,给我们的交通拥堵也带来了很严重的问题,那么在这个时候很多人都特别的喜……因为这些原因,近期快递速度变慢了记者白帆编辑近日,网上不断有消费者反馈称收不到快递。一位消费者表示,自己在网上买了猫粮,但快递迟迟不到,无奈之下只能临时找其他渠道买到了猫咪不太熟悉的猫粮,以……自主高端车鼻祖,品质不输丰田,6年超长质保,为何还是凉了?近几年,自主品牌正在逐步成为购车人群的主流选择,为了在高端市场占据一席之地,很多车企旗下都推出了高端品牌,且关注度也很高。大家都熟知的自主高端车无非是吉利汽车的领克和长城汽车的……
彪准态度不要让近视成为国民之殇今天,我孩子同学的妈妈给我爱人打电话说,她家孩子在眼镜店进行常规的视力检测,竟然发现孩子突然之间近视到了300度!听着她焦急的语气,我爱人连忙安慰说,别着急,眼镜店的检测……为什么开自动挡汽车简单了,可是却容易出交通事故呢?自动挡操作的确简单,也并不容易出现事故;但如今的自动挡车太多了,是手动挡的几倍;甚至从B级车往上就没有手动挡了,那是不是所有B级以上的车型出现交通事故就都得把责任赖在自动挡上?……自己带车跑滴滴,早上6点跑到晚上11点,大概能有多少收入?你好,我就是一名滴滴司机,但是现在我已经不干了!给你总结几点原因你参考一下。1,要看你所在的城市是几线城市,如果城市较大人口较多,那一个月可以过万是没有问题的,除去开支也……丰田雷凌低配全款多少钱呢?丰田雷凌定位是一款紧凑型车,在国内有着较高的知名度,自上市以来有着不错的销量和口碑,延续了丰田质量稳定,省油耐用等特点,获得了消费者的广泛好评,经过全新换代后,新车基于丰田TN……陈梦晒美照,女乒世界第一,颜值也到巅峰,网友称赞韩剧女主角北京时间2022年1月3日,国乒女队主力、现任世界第一的陈梦发布了动态,在青海海边看海,穿着一身白色的羽绒服,黑色的帽子绒毛,戴着厚厚的手套,披肩的中短发,面色红润,看起来非常……茶水兄弟合轰72分!勇士逆转开拓者4连胜,利拉德又被偷表NBA常规赛捉对厮杀,勇士坐镇主场迎战开拓者,本场库里、维金斯、努尔基奇等多人缺阵,追梦赛前为小佩顿颁发总冠军戒指。比赛上来,勇士就迅速进入状态打出一波90的完美开局,首……穿针织衫高腰半身裙,教你如何摆脱路人感,小个子女生穿更时髦怎样将针织衫穿出高级感半身裙怎么穿才时髦入冬后,厚外套内搭无疑被针织衫包圆了。针织衫作为秋冬最火的经典百搭单品,温柔高级又保暖,用它与高腰半身裙混搭在一起,兼具显瘦显高的……买车不买白色?交警教你一句买车顺口溜照着买不会吃亏随着经济与社会环境的不断变化,现在汽车已经成为了很多人生活中必不可少的一件消耗物品了。汽车能够给我们带来出行上的方便,在一些时候也是一种身份的象征。如今不说普通家用车,就连一些……老司机停车为什么要车头朝外?不开玩笑,性命攸关!点击关注网罗贵州最新最全资讯来源:高质量生活家微路况人民日报科普中国很多车主在停车时,都习惯将车头一股脑直接扎进车位里,觉得这样简单方便。但是不知大家发现没有……为什么倒车总是倒不好?老司机教你两招搞定倒车入库不少人考完驾照后,上路行驶的时候总是前怕狼后怕虎,心里害怕的不行。特别是到某个地方要倒车停车的时候,自己先吓自己,弄得人心惶惶。因为相比车辆前进,要倒车入库的难度相对更高,而且……大跌1000元吨!300万吨产能掀起检修潮,需求降温,原料全眼看金三就要来了,又一原料居然齐齐检修事实证明,这需求是真的不行!涨势昙花一现,300万吨产能迎来检修!聚丙烯(PP):最近PP可谓是易跌难涨,2个月前……比亚迪秦DMi和新款轩逸如何选择,价格都差不多,好纠结哦?两车除价格重合以外其他方面差距巨大在1015万的价格区间段里,曾经销量最高的轿车是轩逸,现在销量接近轩逸的是秦PLUS系列,选择哪辆车好呢?解读这个问题之前需要先讲……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网