经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
SpringBoot + 自定义注解,实现用户操作日志(支持SpEL表达式)
来源:cnblogs  作者:雨点的名字  时间:2023/9/11 9:05:29  对本文有异议

背景

一个成熟的系统,都会针对一些关键的操作,去创建用户操作日志。

比如:

  1. XX人创建了一条订单,订单号:XXXXXXXXX

因为操作人或者订单号是动态的,所以有些开发人员,不知道获取,就将这种操作日志和业务代码融在一起。

我们当然要杜绝这种现象,一定会有更好的解决方案。

当前项目除了满足上面这个基础需求场景外,还可以满足一些常见的日志记录需求。

下面通过一些测试用例来了解下当前项目吧。

一、支持SpEL表达式

1、使用场景

我们在记录操作日志的时候,为了获取接口中的入参信息,就可以通过SpEL表达式。

2、接口示例

  1. @GetMapping(value = "/queryUser")
  2. @OperateLog(bizNo = "{#userName}", operateName = "查询用户", operateContent = "通过 {#userName} 查询用户")
  3. public Result<String> queryUser(@RequestParam String userName) {
  4. return Result.success(userName);
  5. }

这里入参 userName 的获取,就是通过SpEL表达式获取到

3、请求接口

  1. http://localhost:8080/queryUser?userName=James

4、输出日志

  1. 日志操作记录------ OperateLogDTO(operator=张三, bizNo=James, operateName=查询用户, operateContent=通过 James 查询用户, status=true, errMsg=null)

可以看出通过SpEL表达式,已经将 {#userName} 占位符,成功替换请求的参数 James


二、支持函数表达式

1、使用场景

有些时候我们仅仅是获取请求参数的数据还不够,还需要拿着请求参数的数据,去请求其它接口,才能组成一条完整的日志,最典型的场景就是

  1. 商品ID XXX 的商品的名称已经从 XXX 改成 XXX

这里前端肯定只会传当前的商品ID和当前修改后的商品名称,也就是说该商品老的名称还需要通过商品ID去商品表查完后,才能组成完整日志。

2、接口示例

  1. @GetMapping(value = "/deleteUser")
  2. @OperateLog(bizNo = "{#userId}", operateName = "删除用户",
  3. operateContent = "用户id为 {#userId} 用户名为 [getUserNameByUserId{#userId}] 已被删除")
  4. public Result<Void> deleteUser(Long userId) {
  5. return Result.success();
  6. }

3、请求接口

  1. http://localhost:8080/deleteUser?userId=888

4、输出日志

  1. 日志操作记录------ OperateLogDTO(operator=张三, bizNo=888, operateName=删除用户, operateContent=用户id 888 用户名为 张老三 已被删除, status=true, errMsg=null)

这里用户名张老三,是模拟查询数据库获取的用户名。


三、支持三目表达式

1、使用场景

有时候我们可能根据是否传主键id来判断是新增还是更新,或者传不同的type来确定什么操作类型。

2、接口示例

  1. @PostMapping(value = "/saveOrUpdateUser")
  2. @OperateLog(bizNo = "{#dto.userId}", operateName = "#dto.userId == null ? '新增用户':'更新用户'",
  3. operateContent = "#dto.userId == null ? '新增' + #dto.userName + '用户':'将用户id为' + #dto.userId + '的用户名更新为' + #dto.userName")
  4. public Result<Void> saveOrUpdateUser(@RequestBody UserDTO dto) {
  5. return Result.success();
  6. }

3、请求示例

请求url

  1. localhost:8080/saveOrUpdateUser

请求参数

  1. {
  2. "userId": 17,
  3. "userName": "赵磊"
  4. }

4、输出日志

传入userId的日志

  1. 日志操作记录------ OperateLogDTO(operator=张三, bizNo=null, operateName=更新用户, operateContent=将用户id17的用户名更新为赵磊, status=true, errMsg=null)

如果不传入userId只传userName,我们再看下日志

  1. 日志操作记录------ OperateLogDTO(operator=张三, bizNo=null, operateName=新增用户, operateContent=新增赵磊用户, status=true, errMsg=null)

四、支持标记成功日志或业务异常日志

1、使用场景

请求一个接口的时候,可以分为三种情况:

  • 接口返回成功,同时返回成功状态码
  • 接口返回成功,但返回业务异常状态码,比如:没有查询到该订单信息
  • 接口直接报错,比如我们常见的空指针异常

对于第三种情况,我们可以不去记录这个用户操作日志,如果有需要可以记录在异常记录表中。

但对于第一和第二种情况,我们需要记录操作是成功还是失败。

2、接口示例

  1. @PostMapping(value = "/saveUser")
  2. @OperateLog(bizNo = "{#dto.userId}", operateName = "新增用户", operateContent = "新增用户名为{#dto.userName}")
  3. public Result<Void> saveUser(@RequestBody UserDTO dto) {
  4. return Result.failed("该用户名称已存在");
  5. }

可以看出接口返回的是 该用户名称已存在,业务异常。

3、请求示例

请求url

  1. localhost:8080/saveUser

请求参数

  1. {
  2. "userId": 2,
  3. "userName": "阎平"
  4. }

4、输出日志

  1. 日志操作记录------ OperateLogDTO(operator=张三, bizNo=2, operateName=新增用户, operateContent=新增用户名为阎平, status=false, errMsg=该用户名称已存在)

可以看出这里的status状态是 false,同时记录了错误原因 该用户名称已存在

最后附上GitHub源码地址:

https://github.com/yudiandemingzi/spring-boot-operate-log



声明: 公众号如需转载该篇文章,发表文章的头部一定要 告知是转至公众号: 后端元宇宙。同时也可以问本人要markdown原稿和原图片。其它情况一律禁止转载!

原文链接:https://www.cnblogs.com/qdhxhz/p/17684311.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号