SpringBoot和@Aspect实现自建Log日志功能

简介: SpringBoot和@Aspect实现自建Log日志功能

主页:写程序的小王叔叔的博客欢迎来访👀

支持:点赞收藏关注


1、技术

JDK1.8+

SpringBoot2.0+   、@Aspect注解

MySql5.6+

2、代码干货

Log实体对象类.java

package*****.***.***.modules.sys.log.entity;
importjava.io.Serializable;
importjava.util.Date;
importjavax.persistence.Column;
importjavax.persistence.Entity;
importjavax.persistence.Id;
importjavax.persistence.Table;
importorg.springframework.stereotype.Component;
importio.swagger.annotations.ApiModelProperty;
@Entity@Table(name="sys_log")
@Component@org.hibernate.annotations.Table(comment="系统日志信息", appliesTo="sys_log")
publicclassSysLogimplementsSerializable{
privatestaticfinallongserialVersionUID=42L;
@Id@ApiModelProperty("主键")
@Column(name="id",nullable=false,columnDefinition="bigint(64)  comment '主键'")
privateLongid;// 主键Id@ApiModelProperty("日志编号")
@Column(name="log_id",columnDefinition="varchar(255)  comment '日志编号'" )
privateStringlogId;//日志编号@ApiModelProperty("请求链接")
@Column(name="url",columnDefinition="text  comment '请求链接'" )
privateStringurl;//请求链接@ApiModelProperty("请求方法")
@Column(name="method",columnDefinition="text  comment '请求方法'" )
privateStringmethod;//请求方法@ApiModelProperty("请求类名")
@Column(name="class_name",columnDefinition="text  comment '请求类名'" )
privateStringclassName;//请求方法@ApiModelProperty("请求方法名")
@Column(name="method_name",columnDefinition="text  comment '请求方法名'" )
privateStringmethodName;//请求方法@ApiModelProperty("请求参数")
@Column(name="params",columnDefinition="text  comment '请求参数'" )
privateStringparams;//请求参数@ApiModelProperty("日志类型:(1:系统日志2:业务日志)")
@Column(name="lot_type",columnDefinition="varchar(255)  comment '日志类型:(1:系统日志2:业务日志)'" )
privateStringlogType;//请求方法@ApiModelProperty("请求方式:(GET/POST)")
@Column(name="type",columnDefinition="varchar(255)  comment '请求方式(GET/POST)'" )
privateStringtype;//请求方法@ApiModelProperty("请求IP")
@Column(name="IP",columnDefinition="text  comment '请求IP'" )
privateStringip;//请求方法@ApiModelProperty("操作的数据库表")
@Column(name="log_table",columnDefinition="varchar(255)  comment '操作的数据库表'" )
privateStringtable;//操作的数据库表@ApiModelProperty("请求异常")
@Column(name="log_error",columnDefinition="text  comment '请求异常'" )
privateStringlogError;//请求异常@ApiModelProperty("运行时长")
@Column(name="time",columnDefinition="varchar(255) comment '运行时长'" )
privatelongtime;//@ApiModelProperty("备注")
@Column(name="log_comment",columnDefinition="text  comment '备注'" )
privateStringlogComment;//备注@ApiModelProperty("创建人")
@Column(name="create_by" )
privateStringcreateBy;//创建人@ApiModelProperty("创建时间")
@Column(name="create_time"  )
privateDatecreateTime;//创建时间//setter()/getter();}

3、基本的CRUD

package****.****.****.modules.sys.log.controller;
importjava.util.List;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.CrossOrigin;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.ResponseBody;
importorg.springframework.web.bind.annotation.RestController;
import*****.modules.sys.log.entity.SysLog;
import*******.modules.sys.log.service.SysLogService;
importio.swagger.annotations.ApiOperation;
@CrossOrigin//跨域@RestController@RequestMapping("/SysLog")
publicclassSysLogController{
@AutowiredpublicSysLogServicesysLogService;
//  //添加AOP注解日志管理//  @SysLogAspectValue(//      describtion = "获取所有日志列表信息",//      logType = "1",//      type="POST",//      url="/SysLog/SelectAllSysLog",//      table="sys_log",//      params = "SysLog",//      method = "POST"//  )@ResponseBody@ApiOperation(value="获取所有日志列表信息", notes="/SysLog/SelectAllSysLog")
@GetMapping(value="/SelectAllSysLog")
publicList<SysLog>SelectAllSysLog(){
returnsysLogService.SelectAllSysLogList(page).getContent();
  }
}
package*******.*****.******modules.sys.log.service;
importorg.springframework.data.domain.Page;
import***.***.****t.modules.sys.log.entity.SysLog;
/**** 系统日志接口* @ClassName: SysLogService* @Description: TODO(描述)* @author author* @date 2019-12-03 10:55:22*/publicinterfaceSysLogService {
/**** 日志保存* @Title: save* @Description: TODO(描述)* @param sysLog* @author author* @date 2019-12-10 09:56:28*/voidsave(SysLogsysLog);
}
package***.****.****.modules.sys.log.service.impl;
importjava.util.ArrayList;
importjava.util.List;
importjavax.persistence.criteria.CriteriaBuilder;
importjavax.persistence.criteria.CriteriaQuery;
importjavax.persistence.criteria.Predicate;
importjavax.persistence.criteria.Root;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.data.domain.Page;
importorg.springframework.data.domain.PageRequest;
importorg.springframework.data.domain.Pageable;
importorg.springframework.data.domain.Sort;
importorg.springframework.data.jpa.domain.Specification;
importorg.springframework.stereotype.Service;
import***.***.***.***.****.modules.sys.log.entity.SysLog;
import***.*.*.*.*.*.*.*.modules.sys.log.repository.SysLogRepository;
import*.*.*.*.*.*.*.*.*.*.modules.sys.log.service.SysLogService;
/*** 系统日志实现类* @ClassName: SysLogServiceImpl* @Description: TODO(描述)* @author author* @date 2019-12-03 10:55:17*/@Service("SysLogService")
publicclassSysLogServiceImplimplementsSysLogService{
@AutowiredpublicSysLogRepositorysysLogRepository;
@OverridepublicPage<SysLog>SelectAllSysLogList(intpage) {
Sortsort=newSort(Sort.Direction.DESC, "createTime");//创建时间正序排列Pageablepageable=PageRequest.of(page, this.size, sort);
Page<SysLog>sysLog=sysLogRepository.findAll (newSpecification<SysLog>() {
@OverridepublicPredicatetoPredicate(Root<SysLog>root,
CriteriaQuery<?>query, CriteriaBuildercriteriaBuilder) {
List<Predicate>list=newArrayList<Predicate>();
//拼接 where条件-----------------//---------------------------Predicate[] p=newPredicate[list.size()];
returncriteriaBuilder.and(list.toArray(p));
      }
    }, pageable);
returnsysLog;
  }
@Overridepublicvoidsave(SysLogsysLog) {
sysLogRepository.save(sysLog);
  }
}
package*.*.*.*.*.*.*.modules.sys.log.repository;
importorg.springframework.data.jpa.domain.Specification;
importorg.springframework.data.jpa.repository.JpaRepository;
import*.*.*.*.*.*.*.*.modules.sys.log.entity.SysLog;
/*** 系统日志管理类* @ClassName: SysLogRepository* @Description: TODO(描述)* @author author* @date 2019-12-03 10:55:09*/publicinterfaceSysLogRepositoryextendsJpaRepository<SysLog, Long> {
}

已上就是基本的业务功能中的CRUD的功能,下面就是重点的log的AOP切面功能,,,

4、AOP切面功能动态获取log信息

1)、在每个需要用到的方法头上增加注释,附加案例【四中第一个截图】

package*.*.*.*.*.*.*.*.modules.sys.log.controller;
importjava.lang.annotation.Documented;
importjava.lang.annotation.ElementType;
importjava.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
importjava.lang.annotation.Target;
/**** 系统日志管理表* @ClassName: SysLogController* @Description: TODO(描述)* @author author* @date 2019-12-03 10:54:52*/@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented//注释文档public@interfaceSysLogAspectValue {
Stringdescribtion() default"";//日志描述StringlogType() default"1";//日志种类-1:系统日志2:业务日志Stringtype()  default"GET";//请求方式:(GET/POST)Stringurl()  default"";//请求链接Stringtable()  default"";//操作的数据库表Stringparams()  default"";//请求参数Stringmethod()  default"";//请求方法}

制作切面内容

package*.*.*.*.*.*.*.modules.sys.log.controller;
importjava.lang.reflect.Method;
importjava.util.ArrayList;
importjava.util.Date;
importjava.util.List;
importjavax.servlet.http.HttpServletRequest;
importorg.aspectj.lang.JoinPoint;
importorg.aspectj.lang.ProceedingJoinPoint;
importorg.aspectj.lang.annotation.AfterThrowing;
importorg.aspectj.lang.annotation.Around;
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.Pointcut;
importorg.aspectj.lang.reflect.MethodSignature;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Component;
importorg.springframework.web.context.request.RequestContextHolder;
importorg.springframework.web.context.request.ServletRequestAttributes;
importcom.google.gson.Gson;
import*.*.*.*.*.*.common.utils.IdGenerate;
import*.*.*.*.*.*.modules.sys.log.entity.SysLog;
import*.*.*.*.*.*.modules.sys.log.service.SysLogService;
/****  系统日志切面* @ClassName: SysLogAspect* @Description: TODO(描述)* @author author* @date 2019-12-04 10:34:41*/@Aspect// 使用@Aspect注解声明一个切面@ComponentpublicclassSystemLogAspect{
privatefinalStringPOINT_CUT="@annotation(*.*.*.*.*.modules.sys.log.entity)";
privatestaticfinalorg.slf4j.Loggerlog=org.slf4j.LoggerFactory.getLogger(SystemLogAspect.class);
@AutowiredpublicSysLogServicesysLogService;
/*** 这里我们使用注解的形式* 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method* 切点表达式:   execution(...)*/@Pointcut(POINT_CUT)
publicvoidPointCut() {}
/*** 环绕通知 @Around  , 当然也可以使用 @Before (前置通知)  @After (后置通知)* @param point* @return* @throws Throwable*///@Around(POINT_CUT)@Around("@annotation(SysLogAspectValue)")
publicObjectaround(ProceedingJoinPointpoint) throwsThrowable {
longbeginTime=System.currentTimeMillis();
Objectresult=point.proceed();
try {
//正常保存日志saveLog(point, System.currentTimeMillis() -beginTime);
        } catch (Exceptione) {
//异常保存日志//afterReturningMethod(point, e);        }
returnresult;
    }
/**** 捕获异常* * @Title: afterReturningMethod* @Description: TODO(描述)* @param joinPoint* @param e* @author author* @throws Throwable * @date 2019-12-10 01:40:37*/@AfterThrowing(throwing="exception",value="@annotation(SysLogAspectValue)",argNames="exception")
publicvoidafterReturningMethod(JoinPointjoinPoint, Exceptione) throwsThrowable{
if(e!=null){
SysLogsysLog=newSysLog();
longbeginTime=System.currentTimeMillis();
longtime=System.currentTimeMillis() -beginTime;
MethodSignaturesignature= (MethodSignature) joinPoint.getSignature();
Methodmethod=signature.getMethod();
// 接收到请求,记录请求内容ServletRequestAttributesattributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequestrequest=attributes.getRequest();
sysLog.setId(IdGenerate.longUUIDId());//主键sysLog.setLogId(sysLog.getId().toString());//日志编号sysLog.setTime(time);//时长sysLog.setIp(request.getRemoteAddr());//请求的IPsysLog.setCreateBy(sysLog.getIp());//请求人sysLog.setCreateTime( newDate() );//创建时间SysLogAspectValuesysLogAspectValue=method.getAnnotation(SysLogAspectValue.class);
if(sysLogAspectValue!=null){
//注解上的描述sysLog.setLogComment(sysLogAspectValue.describtion());//备注sysLog.setLogType(sysLogAspectValue.logType());//日志类型sysLog.setType(sysLogAspectValue.type());//请求类型sysLog.setUrl(sysLogAspectValue.url());//请求链接sysLog.setTable(sysLogAspectValue.table());//操作的数据表sysLog.setMethod(sysLogAspectValue.method());//操作请求方法            }
//请求的 类名、方法名sysLog.setClassName(joinPoint.getTarget().getClass().getName());//类名sysLog.setMethodName(signature.getName());//方法名//请求的参数Object[] args=joinPoint.getArgs();
List<String>list=newArrayList<String>();
for (Objecto : args) {
list.add(newGson().toJson(o));
            }
sysLog.setParams("Params:[ "+list.toString()+" ]:Aspectj @AfterThrowing");
sysLog.setLogError(joinPoint.getSignature().getName()+"[ message:"+e.getMessage() +"]:Aspectj @AfterThrowing");
System.out.println("=====异常保存日志成功==============================");
sysLogService.save(sysLog);
log.trace(POINT_CUT, sysLog);
System.out.println("=====异常保存日志  结束=========================");
        }
    }
/*** 正常保存日志* @param joinPoint* @param time* @throws Throwable */publicvoidsaveLog(ProceedingJoinPointjoinPoint, longtime) {
SysLogsysLog=newSysLog();
sysLog=this.addSysLog(joinPoint,sysLog , time );
//请求的参数Object[] args=joinPoint.getArgs();
List<String>list=newArrayList<String>();
for (Objecto : args) {
list.add(newGson().toJson(o));
        }
sysLog.setParams("Params:[ "+list.toString()+" ]:Aspectj @Around");
sysLog.setLogError( "[ message: 无 ]:Aspectj @Around");
System.out.println("=====正常保存日志成功==============================");
sysLogService.save(sysLog);
log.trace(POINT_CUT, sysLog);
System.out.println("=====正常保存日志  结束=========================");
    }
/*** 组装日志model* @Title: addSysLog* @Description: TODO(描述)* @param sysLog* @return* @author author* @date 2019-12-10 02:09:04*/publicSysLogaddSysLog(ProceedingJoinPointjoinPoint, SysLogsysLog , longtime) {
MethodSignaturesignature= (MethodSignature) joinPoint.getSignature();
Methodmethod=signature.getMethod();
// 接收到请求,记录请求内容ServletRequestAttributesattributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequestrequest=attributes.getRequest();
sysLog.setId(IdGenerate.longUUIDId());//主键sysLog.setLogId(sysLog.getId().toString());//日志编号sysLog.setTime(time);//时长sysLog.setIp(request.getRemoteAddr());//请求的IPsysLog.setCreateBy(sysLog.getIp());//请求人sysLog.setCreateTime( newDate() );//创建时间SysLogAspectValuesysLogAspectValue=method.getAnnotation(SysLogAspectValue.class);
if(sysLogAspectValue!=null){
//注解上的描述sysLog.setLogComment(sysLogAspectValue.describtion());//备注sysLog.setLogType(sysLogAspectValue.logType());//日志类型sysLog.setType(sysLogAspectValue.type());//请求类型sysLog.setUrl(sysLogAspectValue.url());//请求链接sysLog.setTable(sysLogAspectValue.table());//操作的数据表sysLog.setMethod(sysLogAspectValue.method());//操作请求方法        }
//请求的 类名、方法名sysLog.setClassName(joinPoint.getTarget().getClass().getName());//类名sysLog.setMethodName(signature.getName());//方法名returnsysLog;
    }
}

生成这个Log切面日志的用法:

image.png


转载声明:本文为博主原创文章,未经博主允许不得转载

⚠️注意 ~

💯本期内容就结束了,如果内容有误,麻烦大家评论区指出!

如有疑问❓可以在评论区💬或私信💬,尽我最大能力🏃‍♀️帮大家解决👨‍🏫!

如果我的文章有帮助到您,欢迎点赞+关注✔️鼓励博主🏃,您的鼓励是我分享的动力🏃🏃🏃~

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
21天前
|
Java
使用Java代码打印log日志
使用Java代码打印log日志
75 1
|
22天前
|
Linux Shell
Linux手动清理Linux脚本日志定时清理日志和log文件执行表达式
Linux手动清理Linux脚本日志定时清理日志和log文件执行表达式
77 1
|
26天前
|
SQL 关系型数据库 MySQL
MySQL数据库,可以使用二进制日志(binary log)进行时间点恢复
对于MySQL数据库,可以使用二进制日志(binary log)进行时间点恢复。二进制日志是MySQL中记录所有数据库更改操作的日志文件。要进行时间点恢复,您需要执行以下步骤: 1. 确保MySQL配置文件中启用了二进制日志功能。在配置文件(通常是my.cnf或my.ini)中找到以下行,并确保没有被注释掉: Copy code log_bin = /path/to/binary/log/file 2. 在需要进行恢复的时间点之前创建一个数据库备份。这将作为恢复的基准。 3. 找到您要恢复到的时间点的二进制日志文件和位置。可以通过执行以下命令来查看当前的二进制日志文件和位
|
23小时前
|
Java
log4j异常日志过滤规则配置
log4j异常日志过滤规则配置
7 0
|
13天前
|
运维 安全 Ubuntu
`/var/log/syslog` 和 `/var/log/messages` 日志详解
`/var/log/syslog` 和 `/var/log/messages` 是Linux系统的日志文件,分别在Debian和Red Hat系发行版中记录系统事件和错误。它们包含时间戳、日志级别、PID及消息内容,由`rsyslog`等守护进程管理。常用命令如`tail`和`grep`用于查看和搜索日志。日志级别从低到高包括`debug`到`emerg`,表示不同严重程度的信息。注意保护日志文件的安全,防止未授权访问,并定期使用`logrotate`进行文件轮转以管理磁盘空间。
19 1
|
14天前
|
网络协议 应用服务中间件 Linux
centos7 Nginx Log日志统计分析 常用命令
centos7 Nginx Log日志统计分析 常用命令
25 2
|
14天前
|
Ubuntu Linux 网络安全
/var/log/auth.log日志详解
`/var/log/auth.log`是Linux(尤其是Debian系如Ubuntu)记录身份验证和授权事件的日志文件,包括登录尝试(成功或失败)、SSH活动、sudo使用和PAM模块的操作。登录失败、SSH连接、sudo命令及其它认证活动都会在此记录。查看此日志通常需root权限,可使用`tail`、`less`或`grep`命令。文件内容可能因发行版和配置而异。例如,`sudo tail /var/log/auth.log`显示最后几行,`sudo grep &quot;failed password&quot; /var/log/auth.log`搜索失败密码尝试。
54 8
|
14天前
|
Java Linux
Springboot 解决linux服务器下获取不到项目Resources下资源
Springboot 解决linux服务器下获取不到项目Resources下资源
|
21天前
|
Java API Spring
SpringBoot项目调用HTTP接口5种方式你了解多少?
SpringBoot项目调用HTTP接口5种方式你了解多少?
71 2
|
21天前
|
前端开发 JavaScript Java
6个SpringBoot 项目拿来就可以学习项目经验接私活
6个SpringBoot 项目拿来就可以学习项目经验接私活
33 0