我们经常会有这样的需求,需要对关键的业务功能做操作日志记录,也就是用户在指定的时间操作了哪个功能,操作前后的数据记录,必要的时候可以一键回退,今天我就为大家实现这个的功能,让大家可以直接拿来用。
首先我们得要分析具体要实现这个功能,都需要记录哪些信息,然后怎么要去实现这个功能?
具体功能点:
我们首先要想到,要实现这个功能,最好的办法就是需要和业务逻辑进行解耦,因为它是一种业务辅助功能,同时是对所有业务的一种横向操作,那我们使用什么技术,是不是就呼之欲出了?最容易想到的就是AOP切面+自定义注解。
1、首先定义操作日志注解,注解内定义一些属性,如操作功能名称、描述等;
2、将自定义注解标记在需要进行业务操作记录的方法上,一般查询不需要。
3、定义切入点,编写切面:切入点就是标记业务操作日志注解的目标方法;切面就是保存业务操作日志信息。
对了,在这里我想给大家说一下咱们经常用到的几个技术的区别,过滤器,拦截器,SpringAOP,这个也是我经常的困惑。
在匹配中同一目标时,过滤器、拦截器、SpringAOP的执行优先级是:过滤器>拦截器>SpringAOP,执行顺序是先进后出,主要有如下区别:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
create table if not exists bus_log
(
id bigint auto_increment comment '自增id'
primary key,
bus_name varchar(100) null comment '业务名称',
bus_descrip varchar(255) null comment '业务操作描述',
oper_person varchar(100) null comment '操作人',
oper_time datetime null comment '操作时间',
ip_from varchar(50) null comment '操作来源ip',
param_file varchar(255) null comment '操作参数报文文件'
)
comment '业务操作日志' default charset ='utf8';
/**
* 业务日志注解
* 可以作用在控制器或其他业务类上,用于描述当前类的功能;
* 也可以用于方法上,用于描述当前方法的作用;
*/
@Target({
ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface BusLog {
/**
* 功能名称
* @return
*/
String name() default "";
/**
* 功能描述
* @return
*/
String descrip() default "";
}
主要步骤是:在环绕通知内执行过目标方法后,获取目标类、目标方法上的业务日志注解上的功能名称和功能描述, 把方法的参数报文写入到文件中,最后保存业务操作日志信息;
@Component
@Aspect
@Slf4j
public class BusLogAop implements Ordered {
@Autowired
private BusLogDao busLogDao;
/**
* 定义BusLogAop的切入点为标记@BusLog注解的方法
*/
@Pointcut(value = "@annotation(com.wuk.BusLog)")
public void pointcut() {
}
/**
* 业务操作环绕通知
*/
@Around("pointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) {
log.info("----BusAop 环绕通知 start");
//执行目标方法
Object result = null;
try {
result = proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
//目标方法执行完成后,获取目标类、目标方法上的业务日志注解上的功能名称和功能描述
Object target = proceedingJoinPoint.getTarget();
Object[] args = proceedingJoinPoint.getArgs();
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
BusLog anno1 = target.getClass().getAnnotation(BusLog.class);
BusLog anno2 = signature.getMethod().getAnnotation(BusLog.class);
BusLogBean busLogBean = new BusLogBean();
String logName = anno1.name();
String logDescrip = anno2.descrip();
busLogBean.setBusName(logName);
busLogBean.setBusDescrip(logDescrip);
busLogBean.setOperPerson("wuk");
busLogBean.setOperTime(new Date());
JsonMapper jsonMapper = new JsonMapper();
String json = null;
try {
json = jsonMapper.writeValueAsString(args);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
//把参数报文写入到文件中
OutputStream outputStream = null;
try {
String paramFilePath = System.getProperty("user.dir") + File.separator + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN) + ".log";
outputStream = new FileOutputStream(paramFilePath);
outputStream.write(json.getBytes(StandardCharsets.UTF_8));
busLogBean.setParamFile(paramFilePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//保存业务操作日志信息
this.busLogDao.insert(busLogBean);
log.info("----BusAop 环绕通知 end");
return result;
}
@Override
public int getOrder() {
return 1;
}
}
@RestController
@Slf4j
@RequestMapping("/person")
public class PersonController {
@Autowired
private IPersonService personService;
@PostMapping
@BusLog(name="添加人员信息",descrip = "添加人员信息")
public Person add(@RequestBody Person person) {
Person result = this.personService.registe(person);
log.info("//增加person执行完成");
return result;
}
@PutMapping
@BusLog(name="修改人员信息",descrip = "修改人员信息")
public void edit(@RequestBody Person person) {
this.personService.update(person);
}
@DeleteMapping
@BusLog(name="删除人员信息", descrip = "删除人员信息")
public void delete(@PathVariable(name = "id") Integer id) {
this.personService.delete(id);
}
}
文章浏览阅读2w次,点赞20次,收藏204次。在Python中有非常多的内置函数,在这里列出来一些经常使用到的内置函数,在编程时如果恰当地使用这些函数会达到事半功倍的效果!本篇博文内容会经常更新,建议收藏_python内置函数
文章浏览阅读1.5k次,点赞2次,收藏10次。计算机实习学习总结报告篇1一、实习单位:来到实习单位后主要是在门市从事产品的销售和商家间渠道工作。在工作的过程中了解计算机相关行业的发展现状及趋势;熟悉计算机硬件组装、计算机系统及软件安装、局域网搭建;掌握典型计算机网络工程的安装与维护;了解网站建设与网站营销、网站美工设计、基于java的动态网站建设并且了解单位营运方式、项目分工、如何进行管理等。虽然整个实习时间较短,但应该说让咱们每个人都还是学到了不少知识和东西,见识到了不少平时课堂中、校园里无法见识到的方方面面也基本圆满完成所有的实习任务。二、实习总结_实习工作总结经验csdn
文章浏览阅读3.2k次,点赞7次,收藏48次。怎么调用python脚本就不详细说了,网上有很多教程,对于我来说主要就是打包的问题比较难解决,弄了一个下午都没解决,不知道是minconda的问题,还是Qt更新的原因,网上的很多解决方法都不行,经过我的一项一项排查,最后发现就是少导了一个文件夹,怕自己后面忘记,所以发个帖子记录一下。_c++ 调用python 打包
文章浏览阅读8.1w次,点赞61次,收藏79次。本文讲解了Langchain+本地大语言模型进行数据库操作的实战代码,希望能对尝试使用开源大语言模型进行SQL操作的同学们有所帮助。文章目录1. 前言2. 代码思路剖析3. 实战代码_langchain执行sql
文章浏览阅读95次。CSS篇1.如何让一个页面有背景图片,并且背景图片铺满整个屏幕? 可以用body,的background属性来设置!例如:background: url("123.jpg") no-repeat fixed center top / 100% 500px transparent; 那么现在把这个属性拆开来解释下。1.background-imag..._java做完项目后的技能与知识积累怎么写 site:blog.csdn.net
文章浏览阅读1.7k次,点赞5次,收藏9次。结合数据手册,分析寄存器_ad7192 id寄存器
文章浏览阅读1.8k次,点赞2次,收藏2次。在我们日常开发中经常会用到ScrollView与RecyclerView的组合,但是这种组合有时会出现滑动不流畅的问题,也就是卡顿现象布局如下:<ScrollView ="http://schemas.android.com/apk/res/android"android:layout_width="match_parent" androi......_android recyclerview scrollview
文章浏览阅读1.3w次,点赞84次,收藏384次。文章目录1、(精)matlab&lingo已编好的程序2、《MATLAB 神经网络30个案例分析》源程序 数据3、《MATLAB神经网络原理与实例精解》随书附带源程序4、《MATLAB图像处理》源文件5、《基于MATLAB的高等数学问题求解》 随书附带源程序6、28个实际问题建模MATLAB源程序代码.rar7、AHP层次分析法8、CellularAutomata元胞向量机9、FuzzyM..._matlab数学模型
文章浏览阅读354次。说明文章的图片来源《MySQL是怎么运行的:从根儿上理解MySQL》,本篇文章只是个人学习总结,欢迎大家买一本看看,对于mysql是由浅入深的讲解非常细致目录说明8.MySQL 的数据目录数据库和文件系统的关系Mysql的数据目录数据目录和安装目录的区别如何确定mysql的数据目录数据目录的结构数据库在文件系统的表示表在文件系统的表示Innodb如何存储表数据系统表空间独立表空间MyISAM是怎么存储数据的视图在文件系统的表示其它文件文件系统对数据库的影响Mysql系统数据库简介总结9.InnoDB的表_mysql的sort_union使用了bitmap
文章浏览阅读956次。前面提到了线程池提交任务有两种方法:无返回值的任务使用public void execute(Runnable command) 方法提交;有返回值的任务使用public <T> Future<T> submit(Callable) 方法提交。下面具体来看下两者的应用以及区别。一、与主线程执行顺序的区别:..._threadpooltaskexecutor submit execute
文章浏览阅读2.7k次,点赞2次,收藏11次。昨天琢磨着 跑一下ECO,苦于这个电脑没有GPU,只能跑CPU版的了,就是run_demo_ECO,配置过程其实不难,主要是把要准备的包都准备好,然后mex -setup对,接下来就顺利了,下面介绍流程:Win7+VS2013+Matlab2016a+Matconvnet-1.0-beta23 直接参考下面这个博客,简单粗暴的教程,步骤简洁详细,没有冗余: http..._eco跟踪算法
文章浏览阅读1.3k次,点赞21次,收藏18次。tensorflow 2 mac os 系统安装 步骤_mac装tensorflow