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 增删改操作日志 实现的更多相关文章

  1. idea社区版+第一个spring boot项目+增删改查+yml修改端口号

    参考:https://www.cnblogs.com/tanlei-sxs/p/9855071.html 中途出现问题时参考了太多 1.下载idea社区版 2.在settings -> Plug ...

  2. Spring Boot WebFlux 增删改查完整实战 demo

    03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello .这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD ...

  3. redis 与 spring整合 hash 增删改操作 list增删改操作

    本人,对于以前redis的学习是非常痛苦的!近期将以前的东西捡起来.以博客的形式存储,以便于以后快速捡起来,并和广大同胞一起分享! 1):简单介绍 redis 是基于C语言开发. redis是一个ke ...

  4. spring boot aop 自定义注解 实现 日志检验 权限过滤

    核心代码: package com.tran.demo.aspect; import java.lang.reflect.Method; import java.time.LocalDateTime; ...

  5. Spring Boot(二):数据库操作

    本文主要讲解如何通过spring boot来访问数据库,本文会演示三种方式来访问数据库,第一种是JdbcTemplate,第二种是JPA,第三种是Mybatis.之前已经提到过,本系列会以一个博客系统 ...

  6. Hibernate4 拦截器(Interceptor) 实现实体类增删改的日志记录

    转自:https://blog.csdn.net/he90227/article/details/44783099 开发应用程序的过程中,经常会对一些比较重要的数据修改都需要写日志.在实际工作的工程中 ...

  7. Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理

    Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理   本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...

  8. ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪

    ASP.NET MVC深入浅出(被替换)   一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...

  9. Spring Boot AOP解析

    Spring Boot AOP 面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. AOP(Aspec ...

随机推荐

  1. jenkins 安装与使用

    1.jenkins下载:https://jenkins.io/zh/download/ 2.将下载好的war包放到tomcat容器下的D:\apache-tomcat-9.0.10\webapps下( ...

  2. 使用python操作HDF5文件

    HDF Hierarchical Data Format,又称HDF5 在深度学习中,通常会使用巨量的数据或图片来训练网络.对于如此大的数据集,如果对于每张图片都单独从硬盘读取.预处理.之后再送入网络 ...

  3. LeetCode刷题 链表专题

    链表专题 链表题目的一般做法 单链表的结构类型 删除节点 方法一 方法二 增加节点 LeedCode实战 LC19.删除链表的倒数第N个结点 解法思路 LC24.两两交换链表中的节点 解法思路 LC6 ...

  4. Git 修改已提交的commit注释

    两种情况: 1.已经将代码push到远程仓库 2.还没将代码push到远程仓库,还在本地的仓库中 这两种情况下的修改大体相同,只是第一种情况最后会多一步 下面来说怎么修改 先搞清楚你要修改哪次的提交注 ...

  5. 关于使用idea工具debug时,断点颜色由红色变成灰色

    在使用断点调试的时候,发现断点由原来的红色变成灰色的,后来发现是由于错误操作将Debug断点t调试禁用了 ,只需要点击禁用按钮取消就可以了 

  6. Nginx支持WebSocket反向代理

    WebSocket是目前比较成熟的技术了,WebSocket协议为创建客户端和服务器端需要实时双向通讯的webapp提供了一个选择.其为HTML5的一部分,WebSocket相较于原来开发这类app的 ...

  7. kali 安装typora

    一.安装 官网下载文件解压,并移动到 /opt 文件夹下 二.赋权 在typora目录的bin文件夹下执行命令 ./typora 会报错[7442:0707/173355.682906:FATAL:s ...

  8. [spojSUBLEX]Lexicographical Substring Search

    建立后缀自动机,对于同一个节点,出现次数是相同的(right的大小),同时满足单调性(长度越长出现次数越少),所以只需要考虑最长的串即可. PS:似乎也并不需要求依次后缀的max,不知道为什么-- 1 ...

  9. Java ArrayList小记

    1.基本用法 ArrayList是一个泛型容器,新建ArrayList需要实例化泛型参数,比如: ArrayList<String> StrList = new ArrayList< ...

  10. 我的获奖记录及 Important Dates in OI

    逊逊的获奖记录/ruo(真的没拿过啥奖,并且大部分都集中在初三阶段,即 2020-2021 赛季): NOIP2018 pj,1=,无游记 CSP-S2019,1=,无游记 APIO2020,Ag,游 ...