来源:blog.csdn.net/weixin_43954303/article/details/113781801
使用方式
基本使用
源码
此组件解决的问题是:「谁」在「什么时间」对「什么」做了「什么事」
本组件目前针对 Spring-boot 做了 Autoconfig,如果是 SpringMVC,也可自己在 xml 初始化 bean
使用方式

基本使用

maven依赖添加SDK依赖<dependency><groupId>io.github.mouzt</groupId><artifactId>bizlog-sdk</artifactId><version>1.0.1</version></dependency>

SpringBoot入口打开开关,添加 @EnableLogRecord 注解
tenant是代表租户的标识,一般一个服务或者一个业务下的多个服务都写死一个 tenant 就可以

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableTransactionManagement
@EnableLogRecord(tenant = "com.mzt.test")
public class Main {public static void main(String[] args) {SpringApplication.run(Main.class, args);}
}

日志埋点

  1. 普通的记录日志
    pefix:是拼接在 bizNo 上作为 log 的一个标识。避免 bizNo 都为整数 ID 的时候和其他的业务中的 ID 重复。比如订单 ID、用户 ID 等
    bizNo:就是业务的 ID,比如订单ID,我们查询的时候可以根据 bizNo 查询和它相关的操作日志
    success:方法调用成功后把 success 记录在日志的内容中
    SpEL 表达式:其中用双大括号包围起来的(例如:{{#order.purchaseName}})#order.purchaseName 是 SpEL表达式。Spring中支持的它都支持的。比如调用静态方法,三目表达式。SpEL 可以使用方法中的任何参数
  @LogRecordAnnotation(success = "{{#order.purchaseName}}下了一个订单,购买商品「{{#order.productName}}」,下单结果:{{#_ret}}",prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")public boolean createOrder(Order order) {log.info("【创建订单】orderNo={}", order.getOrderNo());// db insert orderreturn true;}

此时会打印操作日志 “张三下了一个订单,购买商品「超值优惠红烧肉套餐」,下单结果:true”
2. 期望记录失败的日志, 如果抛出异常则记录fail的日志,没有抛出记录 success 的日志

 @LogRecordAnnotation(fail = "创建订单失败,失败原因:「{{#_errorMsg}}」",success = "{{#order.purchaseName}}下了一个订单,购买商品「{{#order.productName}}」,下单结果:{{#_ret}}",prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")public boolean createOrder(Order order) {log.info("【创建订单】orderNo={}", order.getOrderNo());// db insert orderreturn true;}

其中的 #_errorMsg 是取的方法抛出异常后的异常的 errorMessage。
3. 日志支持种类
比如一个订单的操作日志,有些操作日志是用户自己操作的,有些操作是系统运营人员做了修改产生的操作日志,我们系统不希望把运营的操作日志暴露给用户看到, 但是运营期望可以看到用户的日志以及运营自己操作的日志,这些操作日志的bizNo都是订单号,所以为了扩展添加了类型字段,主要是为了对日志做分类,查询方便,支持更多的业务。

@LogRecordAnnotation(
fail = “创建订单失败,失败原因:「{{#_errorMsg}}」”,
category = “MANAGER”,
success = “{{#order.purchaseName}}下了一个订单,购买商品「{{#order.productName}}」,下单结果:{{#_ret}}”,
prefix = LogRecordType.ORDER, bizNo = “{{#order.orderNo}}”)
public boolean createOrder(Order order) {
log.info("【创建订单】orderNo={}", order.getOrderNo());
// db insert order
return true;
}

  1. 支持记录操作的详情或者额外信息
    如果一个操作修改了很多字段,但是success的日志模版里面防止过长不能把修改详情全部展示出来,这时候需要把修改的详情保存到 detail 字段, detail 是一个 String ,需要自己序列化。这里的 #order.toString() 是调用了 Order 的 toString() 方法。如果保存 JSON,自己重写一下 Order 的 toString() 方法就可以。
 @LogRecordAnnotation(fail = "创建订单失败,失败原因:「{{#_errorMsg}}」",category = "MANAGER_VIEW",detail = "{{#order.toString()}}",success = "{{#order.purchaseName}}下了一个订单,购买商品「{{#order.productName}}」,下单结果:{{#_ret}}",prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")public boolean createOrder(Order order) {log.info("【创建订单】orderNo={}", order.getOrderNo());// db insert orderreturn true;}
  1. 如何指定操作日志的操作人是什么?框架提供了两种方法
    第一种:手工在LogRecord的注解上指定。这种需要方法参数上有operator
@LogRecordAnnotation(fail = "创建订单失败,失败原因:「{{#_errorMsg}}」",category = "MANAGER_VIEW",detail = "{{#order.toString()}}",operator = "{{#currentUser}}",success = "{{#order.purchaseName}}下了一个订单,购买商品「{{#order.productName}}」,下单结果:{{#_ret}}",prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order, String currentUser) {log.info("【创建订单】orderNo={}", order.getOrderNo());// db insert orderreturn true;
}

这种方法手工指定,需要方法参数上有 operator 参数,或者通过 SpEL 调用静态方法获取当前用户。
第二种:通过默认实现类来自动的获取操作人,由于在大部分web应用中当前的用户都是保存在一个线程上下文中的,所以每个注解都加一个operator获取操作人显得有些重复劳动,所以提供了一个扩展接口来获取操作人 框架提供了一个扩展接口,使用框架的业务可以 implements 这个接口自己实现获取当前用户的逻辑, 对于使用 Springboot 的只需要实现 IOperatorGetService 接口,然后把这个 Service 作为一个单例放到 Spring 的上下文中。使用 Spring Mvc 的就需要自己手工装配这些 bean 了。

@Configuration
public class LogRecordConfiguration {@Beanpublic IOperatorGetService operatorGetService() {return () -> Optional.of(OrgUserUtils.getCurrentUser()).map(a -> new OperatorDO(a.getMisId())).orElseThrow(() -> new IllegalArgumentException("user is null"));}
}//也可以这么搞:
@Service
public class DefaultOperatorGetServiceImpl implements IOperatorGetService {@Overridepublic OperatorDO getUser() {OperatorDO operatorDO = new OperatorDO();operatorDO.setOperatorId("SYSTEM");return operatorDO;}
}
  1. 日志文案调整
    对于更新等方法,方法的参数上大部分都是订单ID、或者产品ID等, 比如下面的例子:日志记录的success内容是:“更新了订单{{#orderId}},更新内容为…”,这种对于运营或者产品来说难以理解,所以引入了自定义函数的功能。使用方法是在原来的变量的两个大括号之间加一个函数名称 例如 “{ORDER{#orderId}}” 其中 ORDER 是一个函数名称。只有一个函数名称是不够的,需要添加这个函数的定义和实现。可以看下面例子 自定义的函数需要实现框架里面的IParseFunction的接口,需要实现两个方法:
    functionName() 方法就返回注解上面的函数名;
    apply()函数参数是 "{ORDER{#orderId}}"中SpEL解析的#orderId的值,这里是一个数字1223110,接下来只需要在实现的类中把 ID 转换为可读懂的字符串就可以了, 一般为了方便排查问题需要把名称和ID都展示出来,例如:"订单名称(ID)"的形式。

这里有个问题:加了自定义函数后,框架怎么能调用到呢?答:对于Spring boot应用很简单,只需要把它暴露在Spring的上下文中就可以了,可以加上Spring的 @Component 或者 @Service 很方便

爽!一个注解,搞定 SpringBoot 操作日志相关推荐

  1. Java后端:一个注解搞定 Spring Boot 日志!

    此组件解决的问题是: 「谁」在「什么时间」对「什么」做了「什么事」 本组件目前针对 Spring-boot 做了 Autoconfig,如果是 SpringMVC,也可自己在 xml 初始化 bean ...

  2. 一个注解搞定 SpringBoot 接口防刷,还有谁不会?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:CS打赢你 blog.csdn.net/weixin ...

  3. 一个注解搞定接口防刷!还有谁不会?

    点击关注公众号,Java干货及时送达 说明:使用了注解的方式进行对接口防刷的功能,非常高大上,本文章仅供参考 一,技术要点:springboot的基本知识,redis基本操作, 首先是写一个注解类: ...

  4. 数据翻译的代码辅助插件,一个注解搞定,减少30%SQL代码量

    一.开源项目简介 Easy Trans是一款用于做数据翻译的代码辅助插件,利用MyBatis Plus/JPA/BeetlSQL 等ORM框架的能力自动查表,让开发者可以快速的把ID/字典码 翻译为前 ...

  5. 自定义注解妙用,一行代码搞定用户操作日志记录,你学会了吗?

    来源:https://blog.csdn.net/yjt520557/article/details/85099115 | 简介 我在使用spring完成项目的时候需要完成记录日志,我开始以为Spri ...

  6. 自定义注解妙用,一行代码搞定用户操作日志记录

    1.简介 在使用spring完成项目的时候需要完成记录日志,开始以为Spring 的AOP功能,就可以轻松解决,半个小时都不用,可是经过一番了解过后,发现一般的日志记录,只能记录一些简单的操作,例如表 ...

  7. Android线程创建aop,【android安卓】一个注解搞定线程切换,基于AOP的线程转换框架...

    最简单的使用方法: 模拟进度展示: @RunOnIOThread public void progress() { for (int i = 0; i <= 100; i++) { showPr ...

  8. thinkjdbc 关闭_ThinkJD: ThinkJD,又名ThinkJDBC,一个强大的开源JDBC/ORM操作库,让你尽可能简洁地用一行代码搞定数据库操作。...

    1 简介 ThinkJD,又名ThinkJDBC,一个简洁而强大的开源JDBC操作库.你可以使用Java像ThinkPHP框架的M方法一样,一行代码搞定数据库操作.ThinkJD会自动管理数据库连接, ...

  9. 开源作品ThinkJDBC—一行代码搞定数据库操作

    1 简介 ThinkJD,又名ThinkJDBC,一个简洁而强大的开源JDBC操作库.你可以使用Java像ThinkPHP框架的M方法一样,一行代码搞定数据库操作.ThinkJD会自动管理数据库连接, ...

最新文章

  1. ios怎样在一个UIImageButton的里面加一些自己定义的箭头
  2. opencv问题解析
  3. 【No.7 C++对象的构造与析构时间】
  4. 数据结构折半查找例题_数据结构第9章例题与答案
  5. linux系统下装windows双系统,LINUX下安装WINDOWS双系统
  6. [BUG]Ubuntu server 16.04安装,无网卡驱动解决
  7. Java-集合第六篇操作集合的工具类Collections
  8. centos 7 iso u盘安装_树莓派Raspberry Pi 4B安装VMware ESXi
  9. python 加注拼音-python汉字注音
  10. 星淘惠:我国在国际大变革中迎来国际贸易的发展黄金时期
  11. 【ARM基础概念:ARMv7架构,ARM(ARM7、ARM9)、Cortex-M4、M7等内核、MCU、MPU、SOC,STM32的一些概念】
  12. Venmo、Bakkt、MoneyGram、Uphold的前高管加入Roxe全球支付网络
  13. 近十年量化交易领域最重要的十本参考书是哪些
  14. Mock工具之Moco使用教程
  15. 配置失败还原请勿关闭计算机,win7系统遇到更新失败提示“配置windwos update 失败还原更改,请勿关闭计算机”的解决方法...
  16. 姚晨为何可以新浪微博排名第一
  17. 优秀课件笔记之人力资源开发与管理导论
  18. python腐蚀膨胀代码_Python图像处理--膨胀与腐蚀
  19. 《硅谷钢铁侠》听书笔记
  20. 中国航空研究所631计算机研究所怎么样,中国航空研究院631所计算机科学与技术怎么样...

热门文章

  1. 基于S-Function的Joystick Input
  2. pwm一个时间单位_「硬见小百科」什么是PWM“死区”?
  3. C语言bool类型定义
  4. 【转】FILE *fp fopen 参数
  5. 万兆电口网卡性能分析
  6. 关于工厂类app的一些想法
  7. vm-install vmware tools安装
  8. 关于Eclipse的使用入门
  9. 用“分区助手”(PartAssist)给C盘扩容
  10. GPU与GPGPU泛淡