news 2026/8/19 22:30:39

Spring Boot AOP记录用户操作日志

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot AOP记录用户操作日志

一、添加依赖

在Spring框架中,使用AOP配合自定义注解可以方便的实现用户操作的监控。首先搭建一个基本的Spring Boot Web环境开启Spring Boot,然后引入必要依赖:

<!-- aop依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.22</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>

二、自定义注解

定义一个方法级别的@Log注解,用于标注需要监控的方法:

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceLog{Stringvalue()default"";}

三、创建库表和实体

3.1 建表

在数据库中创建一张sys_log表,用于保存用户的操作日志,数据库采用mysql5.7.23

droptableifexists`sys_log`;createtable`sys_log`(`id`int(20)notnullauto_incrementcomment'id',`username`varchar(50)charactersetutf8collateutf8_general_cinullcomment'用户名',`operation`varchar(50)charactersetutf8collateutf8_general_cinullcomment'用户操作',`time`int(11)nullcomment'响应时间',`method`varchar(200)charactersetutf8collateutf8_general_cinullcomment'请求方法',`params`varchar(500)charactersetutf8collateutf8_general_cinullcomment'请求参数',`ip`varchar(64)charactersetutf8collateutf8_general_cinullcomment'ip地址',`create_time`DATETIMEnullcomment'创建时间',primarykey(`id`)usingbtree)engine=innodbauto_increment=1characterset=utf8collate=utf8_general_ci row_format=dynamic;

3.2 创建实体

库表对应的实体:

@Getter@SetterpublicclassSysLogimplementsSerializable{privatestaticfinallongserialVersionUID=-6309732882044872293L;privateIntegerid;privateStringusername;privateStringoperation;privateIntegertime;privateStringmethod;privateStringparams;privateStringip;@JsonFormat(timezone="GMT+8",pattern="yyyy-MM-dd HH:mm:ss")privateDatecreateTime;}

四、保存日志的方法

为了方便,这里直接使用Spring JdbcTemplate来操作数据库。定义一个SysLogDao接口,包含一个保存操作日志的抽象方法:

publicinterfaceSysLogDao{voidsaveSysLog(SysLogsyslog);}

其实现方法:

@RepositorypublicclassSysLogDaoImplimplementsSysLogDao{@AutowiredprivateJdbcTemplatejdbcTemplate;@OverridepublicvoidsaveSysLog(SysLogsyslog){StringBuffersql=newStringBuffer("insert into sys_log ");sql.append("(username,operation,time,method,params,ip,create_time) ");sql.append("values(:username,:operation,:time,:method,");sql.append(":params,:ip,:createTime)");NamedParameterJdbcTemplatenpjt=newNamedParameterJdbcTemplate(this.jdbcTemplate.getDataSource());npjt.update(sql.toString(),newBeanPropertySqlParameterSource(syslog));}}

五、切面和切点

定义一个LogAspect类,使用@Aspect标注让其成为一个切面,切点为使用@Log注解标注的方法,使用@Around环绕通知:

@Aspect@ComponentpublicclassLogAspect{@AutowiredprivateSysLogDaosysLogDao;@Pointcut("@annotation(com.wno704.boot.aspect.Log)")publicvoidpointcut(){}@Around("pointcut()")publicObjectaround(ProceedingJoinPointpoint){Objectresult=null;longbeginTime=System.currentTimeMillis();try{// 执行方法result=point.proceed();}catch(Throwablee){e.printStackTrace();}// 执行时长(毫秒)longtime=System.currentTimeMillis()-beginTime;// 保存日志saveLog(point,time);returnresult;}privatevoidsaveLog(ProceedingJoinPointjoinPoint,longtime){MethodSignaturesignature=(MethodSignature)joinPoint.getSignature();Methodmethod=signature.getMethod();SysLogsysLog=newSysLog();LoglogAnnotation=method.getAnnotation(Log.class);if(logAnnotation!=null){// 注解上的描述sysLog.setOperation(logAnnotation.value());}// 请求的方法名StringclassName=joinPoint.getTarget().getClass().getName();StringmethodName=signature.getName();sysLog.setMethod(className+"."+methodName+"()");// 请求的方法参数值Object[]args=joinPoint.getArgs();// 请求的方法参数名称LocalVariableTableParameterNameDiscovereru=newLocalVariableTableParameterNameDiscoverer();String[]paramNames=u.getParameterNames(method);if(args!=null&&paramNames!=null){Stringparams="";for(inti=0;i<args.length;i++){params+=" "+paramNames[i]+": "+args[i];}sysLog.setParams(params);}// 获取requestHttpServletRequestrequest=HttpContextUtils.getHttpServletRequest();// 设置IP地址sysLog.setIp(IPUtils.getIpAddr(request));// 模拟一个用户名sysLog.setUsername("mrbird");sysLog.setTime((int)time);sysLog.setCreateTime(newDate());// 保存系统日志sysLogDao.saveSysLog(sysLog);}}

六、测试

TestController:

@RestControllerpublicclassTestController{@Log("执行方法一")@GetMapping("/one")publicvoidmethodOne(Stringname){}@Log("执行方法二")@GetMapping("/two")publicvoidmethodTwo()throwsInterruptedException{Thread.sleep(2000);}@Log("执行方法三")@GetMapping("/three")publicvoidmethodThree(Stringname,Stringage){}}

最终项目目录如下图所示:

启动项目,分别访问:

http://localhost:8080/web/one?name=wno704

http://localhost:8080/web/two

http://localhost:8080/web/three?name=wno704&age=28

查询数据库:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/19 22:30:11

嵌入式开发入门:从LED与传感器控制到物联网系统构建

1. 从零开始&#xff1a;为什么我们需要控制LED和传感器&#xff1f;如果你刚接触电子制作&#xff0c;比如Arduino或者ESP32&#xff0c;你可能会觉得“控制LED和传感器”听起来太基础了&#xff0c;不就是让灯亮一下、读个数吗&#xff1f;我刚开始也是这么想的&#xff0c;但…

作者头像 李华
网站建设 2026/8/19 22:29:46

基于EasyUI与KnockoutJS的通用分页查询与数据导出ViewModel设计

1. 项目缘起&#xff1a;从重复劳动到统一抽象 在基于EasyUI、KnockoutJS和MVC 4.0技术栈的中后台管理系统中&#xff0c;分页查询和数据导出几乎是每个列表页面的标配功能。回想几年前&#xff0c;我接手一个项目&#xff0c;光是用户管理、订单管理、日志查询等模块&#xff…

作者头像 李华
网站建设 2026/8/19 22:26:35

广州微闻网络AI落地技术实践:Agent定制、Token供应与云计算全栈技术解析

文聚焦广州微闻网络科技有限公司在AI落地领域的技术实践&#xff0c;深入解析Agent定制开发、Token聚合供应、云计算全栈服务三大技术方向的具体实现方案&#xff0c;并涵盖AI提效、AI转型培训、WorkBuddy使用培训等业务的技术能力&#xff0c;为技术团队提供参考。一、公司技术…

作者头像 李华
网站建设 2026/8/19 22:24:38

在线教育平台开课前三网验收:视频域、直播与 API

在线教育平台开课前三网验收&#xff1a;视频域、直播与 API工具地址&#xff1a;https://www.speedce.com 社区论坛&#xff1a;https://bbs.speedce.com 联系&#xff1a;speedceadsgmail.com写在前面 开课铃响了你才发现视频域移动红——太晚了。 本文是一份围绕「在线教育平…

作者头像 李华
网站建设 2026/8/19 22:24:26

多个人同时提问但位置有限

摘要&#xff1a;在算力昂贵的大模型&#xff08;LLM&#xff09;推理与高并发后端架构中&#xff0c;资源的物理约束是不可跨越的红线。假设系统只有 3 个 GPU 槽位&#xff08;Inference Slots / Worker Threads&#xff09;&#xff0c;当 10 个并发请求同时涌入时&#xff…

作者头像 李华
网站建设 2026/8/19 22:22:02

UnrealPakViewer 完整上手教程:三步摸清任意 UE4 Pak 文件内部结构

UnrealPakViewer 完整上手教程&#xff1a;三步摸清任意 UE4 Pak 文件内部结构 【免费下载链接】UnrealPakViewer 查看 UE4 Pak 文件的图形化工具&#xff0c;支持 UE4 pak/ucas 文件 项目地址: https://gitcode.com/gh_mirrors/un/UnrealPakViewer 遇到打好的 UE4 工程…

作者头像 李华