spring-boot aop 增删改操作日志 实现
1.注解接口:
import com.github.wxiaoqi.security.common.constant.Constants;
import java.lang.annotation.*;
/**
* 日志注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLogOpt {
String value();
String module() default ""; //模块名称 系统管理-用户管理-列表页面
String description() default ""; //描述
Constants.LogOptEnum operationType() default Constants.LogOptEnum.UNKNOW;//操作类型
}
2.切面类
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.duiyue.common.mvc.core.APIResponse;
import com.duiyue.common.util.LogUtils;
import com.github.wxiaoqi.security.admin.annotation.SysLogOpt;
import com.github.wxiaoqi.security.admin.biz.SysLogService;
import com.github.wxiaoqi.security.api.entity.SysLog;
import com.github.wxiaoqi.security.common.constant.Constants;
import com.github.wxiaoqi.security.common.context.BaseContextHandler;
import com.github.wxiaoqi.security.common.util.RegexUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
@Slf4j
@Aspect
@Component
public class LogAspect {
/**
* 开始时间
*/
private long startTime = 0L;
@Resource
private SysLogService logService;
@Pointcut("execution(* *..rest..*.*(..)) && @annotation(com.github.wxiaoqi.security.admin.annotation.SysLogOpt)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
startTime = System.currentTimeMillis();
Object result = null;
SysLog sysLogModel = logPre(pjp);
try {
result = pjp.proceed();
} finally {
//查询类型不添加日志
if (Constants.LogOptEnum.QUERY.value() != sysLogModel.getOperationType()) {
if (logAfter(result, sysLogModel).getUserName() != null) {
sysLogModel.setCreateTime(new Date());
sysLogModel.setUpdateTime(new Date());
logService.add(sysLogModel);
}
}
}
return result;
}
private SysLog logPre(ProceedingJoinPoint pjp) throws Exception {
SysLog sysLogModel = new SysLog();
for (Method method : Class.forName(pjp.getTarget().getClass().getName()).getMethods()) {
if (method.getName().equals(pjp.getSignature().getName())) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == pjp.getArgs().length) {
//方法名称
sysLogModel.setOperation(method.getAnnotation(SysLogOpt.class).value());
//操作类型
sysLogModel.setOperationType(method.getAnnotation(SysLogOpt.class).operationType().value());
break;
}
}
}
//获取请求对象
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
startTime = System.currentTimeMillis();
String ip = HttpUtil.getClientIP(request);
//方法名含包名(om.github.wxiaoqi.security.admin.rest.SysLogController.queryListPage)
String classMethod = pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName();
//请求参数
String args = JSON.toJSONString(pjp.getArgs()).replaceAll(RegexUtil.getJSonValueRegex("password"), "****").replaceAll(RegexUtil.getJSonValueRegex("oldPassword"), "****");
sysLogModel.setIp(ip);
sysLogModel.setMethod(classMethod);
sysLogModel.setParams(args);
sysLogModel.setCreateTime(new Date());
sysLogModel.setCreateUser(0L);
sysLogModel.setUpdateUser(0L);
String currentUserName = "";
try {
currentUserName = BaseContextHandler.getUsername();
} catch (Exception e) {
LogUtils.error(log, "", e);
}
if (StringUtils.isNotEmpty(currentUserName)) {
sysLogModel.setUserName(currentUserName);
}
return sysLogModel;
}
private SysLog logAfter(Object result, SysLog sysLogModel) {
APIResponse response = null;
if (result != null) {
response = (APIResponse) result;
}
String currentUserName = "";
try {
currentUserName = BaseContextHandler.getUsername();
} catch (Exception e) {
LogUtils.error(log, "", e);
}
if (StringUtils.isNotEmpty(currentUserName)) {
sysLogModel.setUserName(currentUserName);
}
//返回结果
if (response != null && response.getStatus() == Constants.ResultCodeEnum.SUCCESS.value()) {
sysLogModel.setResult(1);
} else {
sysLogModel.setResult(0);
}
//执行时长(毫秒)
Long spendTime = System.currentTimeMillis() - startTime;
sysLogModel.setProcessTime(spendTime);
return sysLogModel;
}
}
3.控制层使用(方法上使用)。
@SysLogOpt(module = "活动管理", value = "添加活动", operationType = Constants.LogOptEnum.ADD)
(注:枚举类型未给出,自行修改)
spring-boot aop 增删改操作日志 实现的更多相关文章
- idea社区版+第一个spring boot项目+增删改查+yml修改端口号
参考:https://www.cnblogs.com/tanlei-sxs/p/9855071.html 中途出现问题时参考了太多 1.下载idea社区版 2.在settings -> Plug ...
- Spring Boot WebFlux 增删改查完整实战 demo
03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello .这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD ...
- redis 与 spring整合 hash 增删改操作 list增删改操作
本人,对于以前redis的学习是非常痛苦的!近期将以前的东西捡起来.以博客的形式存储,以便于以后快速捡起来,并和广大同胞一起分享! 1):简单介绍 redis 是基于C语言开发. redis是一个ke ...
- spring boot aop 自定义注解 实现 日志检验 权限过滤
核心代码: package com.tran.demo.aspect; import java.lang.reflect.Method; import java.time.LocalDateTime; ...
- Spring Boot(二):数据库操作
本文主要讲解如何通过spring boot来访问数据库,本文会演示三种方式来访问数据库,第一种是JdbcTemplate,第二种是JPA,第三种是Mybatis.之前已经提到过,本系列会以一个博客系统 ...
- Hibernate4 拦截器(Interceptor) 实现实体类增删改的日志记录
转自:https://blog.csdn.net/he90227/article/details/44783099 开发应用程序的过程中,经常会对一些比较重要的数据修改都需要写日志.在实际工作的工程中 ...
- Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理
Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理 本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...
- ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪
ASP.NET MVC深入浅出(被替换) 一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...
- Spring Boot AOP解析
Spring Boot AOP 面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. AOP(Aspec ...
随机推荐
- 设计模式二--模板方法Template method
模式分类: 书籍推荐:重构-改善既有代码的设计 重构获得模式 设计模式:现代软件设计的特征是"需求的频繁变化".设计模式的要点是 "寻找变化点,然后在变化点处应用设计模式 ...
- 探究 Go 源码中 panic & recover 有哪些坑?
转载请声明出处哦~,本篇文章发布于luozhiyun的博客: https://www.luozhiyun.com/archives/627 本文使用的go的源码1.17.3 前言 写这一篇文章的原因是 ...
- [loj574]黄金矿工
记$dep_{x}$为1到$x$的边权和,当$x$上的矿工挖了$y$上的黄金时($y$在$x$子树内),显然$\sum_{e}c_{e}=dep_{y}-dep_{x}$ 由此,对于$u$上权值为$v ...
- HCNP Routing&Switching之组播技术-组播基础
组播技术背景 随着internet网络的不断发展,网络中交互的各种数据.语音.视频信息数量突增:新型的在线直播.网络电视.视频会议等应用也在逐渐兴起:这些业务大多符合点到多点的模式,对信息安全性.传播 ...
- UI自动化测试:App的WebView页面中,当搜索栏无搜索按钮时处理方法
一.遇到的问题 在做移动端的UI自动化测试时,经常会遇到上图所示的搜索框,这里有个麻烦就是搜索框没有"搜索"按钮,UI自动化测试时不能确认搜索. 要解决这个问题,我们可以通过 dr ...
- 洛谷 P5233 - [JSOI2012]爱之项链(Polya 定理+递推)
洛谷题面传送门 首先很明显题目暗示我们先求出符合条件的戒指数量,再计算出由这些戒指能够构成的项链的个数,因此考虑分别计算它们.首先是计算符合条件的戒指数量,题目中"可以通过旋转重合的戒指视作 ...
- 洛谷 P4094 [HEOI2016/TJOI2016]字符串(SA+主席树)
题面传送门 一道码农题---- u1s1 感觉这类题目都挺套路的,就挑个有代表性的题写一篇题解罢. 首先注意到答案满足可二分性,故考虑二分答案 \(mid\),转化为判定性问题. 考虑怎样检验 \(m ...
- 洛谷 P4663 - [BalticOI 2008]魔法石(dp)
题面传送门 A:我该是有多无聊来写这种题的题解啊 B:大概是因为这题题解区里没有题解所以我来写一篇了,说明我有高尚的济世情怀(大雾 跑题了跑题了 首先看到字典序第 \(i\) 小小可以自然地想到按位决 ...
- 关于 n 个 [0,1] 的随机变量第 k 小的期望值
今天做到一道题,感觉里面一个结论有点意思,就到网上扒了篇证明(bushi)下来了. 知乎回答习惯,先抛结论,再给证明(大雾 结论:对于 \(n\) 个取值范围为 \([0,1]\) 的随机变量 \(x ...
- 【机器学*与R语言】2-懒惰学*K*邻(kNN)
目录 1.理解使用KNN进行分类 KNN特点 KNN步骤 1)计算距离 2)选择合适的K 3)数据准备 2.用KNN诊断乳腺癌 1)收集数据 2)探索和准备数据 3)训练模型 4)评估模型的性能 5) ...