简介 无论在什么系统中,日志管理模块都属于十分重要的部分,接下来会通过注解AOPMQ的方式实现一个简易的日志管理系统思路注解:标记需要记录日志的方法AOP:通过AOP增强代码,利用后置异常通知的方式获取相关日志信息,最后使用MQ将日志信息发送到专门处理日志的系统RabbitMQ:利用解耦、异步的特性,协调完成各个微服务系统之间的通信1、日志表结构 表结构(syslog):CREATETABLEsyslog(idint(11)NOTNULLAUTOINCREMENTCOMMENT唯一ID,optidint(11)DEFAULTNULLCOMMENT操作用户id,optnamevarchar(50)DEFAULTNULLCOMMENT操作用户名,logtypevarchar(20)DEFAULTNULLCOMMENT日志类型,logmessagevarchar(255)DEFAULTNULLCOMMENT日志信息(具体方法名),createtimedatetimeDEFAULTNULLCOMMENT创建时间,PRIMARYKEY(id))ENGINEInnoDBAUTOINCREMENT17DEFAULTCHARSETutf8COMMENT系统日志表; 实体类(SysLog):DatapublicclassSysLog{privatestaticfinallongserialVersionUID1L;唯一IDTableId(valueid,typeIdType。AUTO)privateIntegerid;操作用户idprivateIntegeroptId;操作用户名privateStringoptName;日志类型privateStringlogType;日志信息(具体方法名)privateStringlogMessage;创建时间privateDatecreateTime;}2、注解注解(SystemLog): 仅作为标记的作用,目的让JVM可以识别,然后可以从中获取相关信息Target:定义注解作用的范围,这里是方法Retention:定义注解生命周期,这里是运行时Target(ElementType。METHOD)Retention(RetentionPolicy。RUNTIME)publicinterfaceSystemLog{SystemLogEnumtype();}枚举(SystemLogEnum): 限定日志类型范围publicenumSystemLogEnum{SAVELOG(保存),DELETELOG(删除),REGISTERLOG(注册),LOGINLOG(登录),LAUDLOG(点赞),COLLECTLOG(收藏),THROWLOG(异常),;privateStringtype;SystemLogEnum(Stringtype){this。typetype;}publicStringgetType(){returntype;}}3、AOP切面AOP(SysLogAspect): 实现代码的增强,主要通过动态代理方式实现的代码增强。拦截注解,并获取拦截到的相关信息,封装成日志对象发送到MQ队列(生产端)ComponentAspectSlf4jpublicclassSysLogAspect{AutowiredMqStreamstream;切点Pointcut(annotation(cn。zdxh。commons。utils。SystemLog))publicvoidlogPointcut(){}后置通知After(logPointcut())publicvoidafterLog(JoinPointjoinPoint){一般日志SysLogsysLogwrapSysLog(joinPoint);log。info(Log值:sysLog);发送mq消息stream。logOutput()。send(MessageBuilder。withPayload(sysLog)。build());}异常通知AfterThrowing(valuelogPointcut(),throwinge)publicvoidthrowingLog(JoinPointjoinPoint,Exceptione){异常日志SysLogsysLogwrapSysLog(joinPoint);sysLog。setLogType(SystemLogEnum。THROWLOG。getType());sysLog。setLogMessage(sysLog。getLogMessage()e);log。info(异常Log值:sysLog);发送mq消息stream。logOutput()。send(MessageBuilder。withPayload(sysLog)。build());}封装SysLog对象paramjoinPointreturnpublicSysLogwrapSysLog(JoinPointjoinPoint){获取请求响应对象ServletRequestAttributesattributes(ServletRequestAttributes)RequestContextHolder。getRequestAttributes();HttpServletRequestrequestattributes。getRequest();MethodSignaturesignature(MethodSignature)joinPoint。getSignature();SysLogsysLognewSysLog();获取方法全路径StringmethodNamesignature。getDeclaringTypeName()。signature。getName();获取注解参数值SystemLogsystemLogsignature。getMethod()。getAnnotation(SystemLog。class);从header取出tokenStringtokenrequest。getHeader(token);if(!StringUtils。isEmpty(token)){操作人信息IntegeruserIdJwtUtils。getUserId(token);StringusernameJwtUtils。getUsername(token);sysLog。setOptId(userId);sysLog。setOptName(username);}if(!StringUtils。isEmpty(systemLog。type())){sysLog。setLogType(systemLog。type()。getType());}sysLog。setLogMessage(methodName);sysLog。setCreateTime(newDate());returnsysLog;}}3、RabbitMQ消息队列MQ: 这里主要是通过SpringCloudStream集成的RabbitMQSpringCloudStream: 作为MQ的抽象层,已屏蔽各种MQ的各自名词,统称为input、output两大块。可以更方便灵活地切换各种MQ,如kafka、RocketMQ等 (1)定义InputOuput接口(MqStream)ComponentpublicinterfaceMqStream{StringLOGINPUTloginput;StringLOGOUTPUTlogoutput;Input(LOGINPUT)SubscribableChannellogInput();Output(LOGOUTPUT)MessageChannellogOutput();}(2)MQ生产者 注:这里使用到AOP切面的微服务,都属于MQ生产者服务 引入依赖: 这里没有版本号的原因是springcloud已经帮我们管理好各个版本号,已无需手动定义版本号!SpringCloudStreamdependencygroupIdorg。springframework。cloudgroupIdspringcloudstreamartifactIddependencydependencygroupIdorg。springframework。cloudgroupIdspringcloudstreambinderrabbitartifactIddependency 在程序入口开启MQ的InputOutput绑定:SpringBootApplication(scanBasePackages{cn。zdxh。user,cn。zdxh。commons})EnableEurekaClientMapperScan(cn。zdxh。user。mapper)EnableBinding(MqStream。class)开启绑定EnableFeignClientspublicclassYouquServiceProviderUserApplication{publicstaticvoidmain(String〔〕args){SpringApplication。run(YouquServiceProviderUserApplication。class,args);}} yml配置: 在生产者端设置outputdestination:相当于rabbitmq的exchangegroup:相当于rabbitmq的queue,不过是和destination一起组合成的queue名binder:需要绑定的MQSpringCloudStream相关配置spring:cloud:stream:bindings:exchange与queue绑定logoutput:日志生产者设置outputdestination:log。exchangecontenttype:applicationjsongroup:log。queuebinder:youqurabbit自定义名称binders:youqurabbit:自定义名称type:rabbitenvironment:spring:rabbitmq:host:localhostport:5672username:guestpassword:25802580 注:完成以上操作,即完成MQ生产端的所有工作(3)MQ消费者 引入依赖、开启InputOutput绑定:均和生产者的设置一致 yml配置: 在生产者端设置inputspring:cloud:SpringCloudStream相关配置stream:bindings:exchange与queue绑定loginput:日志消费者设置inputdestination:log。exchangecontenttype:applicationjsongroup:log。queuebinder:youqurabbitbinders:youqurabbit:type:rabbitenvironment:spring:rabbitmq:host:localhostport:5672username:guestpassword:25802580 消费者监听(LogMqListener): 监听生产者发过来的日志信息,将信息添加到数据库即可ServiceSlf4jpublicclassLogMqListener{AutowiredSysLogServicesysLogService;StreamListener(MqStream。LOGINPUT)publicvoidinput(SysLogsysLog){log。info(开始记录日志);sysLogService。save(sysLog);log。info(结束记录日志);}} 注:完成以上操作,即完成MQ消费端的所有工作4、应用 简述: 只需将SystemLog(typeSystemLogEnum。REGISTERLOG),标记在需要记录的方法上,当有客户端访问该方法时,就可以自动完成日志的记录 5、总结 流程: 注解标记AOP拦截日志发送到MQ专门处理日志的系统监听MQ消息日志插入到数据库 来源:blog。csdn。netweixin38802061articledetails105458047