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. "简单"的优化--希尔排序也没你想象中那么难

    写在前边 大家好,我是melo,一名大二上软件工程在读生,经历了一年的摸滚,现在已经在工作室里边准备开发后台项目啦. 不过这篇文章呢,还是想跟大家聊一聊数据结构与算法,学校也是大二上才开设了数据结构这 ...

  2. ubuntu install redis

    ubuntu install redis apt-get update apt-get install redis-server redis-server --daemonize yes

  3. 在linux 环境下 安装php

    最近打算学写一个php 脚本~ 到了虚拟机环境上发现~没有环境. 只有老老实实去装一个php环境咯. 第一步 去官网下一个包 记得一定要下载tgz格式的 第二步~当然是传上虚拟机上咯~任意目录都可以. ...

  4. Django笔记&教程 5-2 进阶查询——Queryset

    Django 自学笔记兼学习教程第5章第2节--进阶查询--Queryset 点击查看教程总目录 Queryset相关内容其实蛮多的,本文只介绍一些常用的,详细的推荐查询官方文档:queryset-a ...

  5. Study Blazor .NET(二)安装

    翻译自:Study Blazor .NET,转载请注明. 安装 请根据下面步骤安装开始使用Blazor: 1.针对不同的操作系统,安装最新版.Net Core框架 [这里] 2.用.Net Core ...

  6. vue 3 学习笔记 (六)——watch 、watchEffect 新用法

    选项式API与之前写法相同,本篇文章主要通过 Options API 和 Composition API 对比 watch 的使用方法,让您快速掌握 vue3 中 watch 新用法.建议收藏! 一. ...

  7. ICCV2021 | PnP-DETR:用Transformer进行高效的视觉分析

    ​  前言  DETR首创了使用transformer解决视觉任务的方法,它直接将图像特征图转化为目标检测结果.尽管很有效,但由于在某些区域(如背景)上进行冗余计算,输入完整的feature maps ...

  8. SpringCloud微服务实战——搭建企业级开发框架(二十二):基于MybatisPlus插件TenantLineInnerInterceptor实现多租户功能

    多租户技术的基本概念:   多租户技术(英语:multi-tenancy technology)或称多重租赁技术,是一种软件架构技术,它是在探讨与实现如何于多用户的环境下共用相同的系统或程序组件,并且 ...

  9. Vulnhub-Empire: Breakout题解

    Vulnhub-Empire: Breakout题解 这是Empire系列的靶机Breakout,地址:Vulnhub-EMPIRE: BREAKOUT 目标扫描 使用arp-scan 命令识别靶机I ...

  10. flutter第一课

    网上搜到有一个8小时体验flutter的教程,感觉可以尝试一个hello world出来:https://www.jianshu.com/p/9aaabc60d8af 官网下载很慢,可以使用镜像下载, ...