springboot整合AOP,实现log操作日志

2023-11-06

添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

编写注解

package com.ly.common.annotation;


import com.ly.common.enums.BusinessType;
import com.ly.common.enums.OperatorType;
import java.lang.annotation.*;

/**
 * 自定义操作日志记录注解
 * 
 * @author ruoyi
 */
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
    /**
     * 模块 
     */
    String title() default "";

    /**
     * 功能
     */
    BusinessType businessType() default BusinessType.OTHER;

    /**
     * 操作人类别
     */
    OperatorType operatorType() default OperatorType.MANAGE;

    /**
     * 是否保存请求的参数
     */
    boolean isSaveRequestData() default true;
}

编写aop

package com.ly.provider.aspectj;


import com.ly.common.annotation.Log;
import com.ly.common.enums.BusinessStatus;
import com.ly.common.utils.ServletUtils;
import com.ly.common.utils.json.JsonUtils;
import com.ly.provider.sys.Service.SysOperLogService;
import com.ly.provider.sys.entity.SysOperLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * 操作日志记录处理
 * 
 * @author ruoyi
 */
@Aspect
@Component
public class LogAspect
{
    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);

    @Autowired
    private SysOperLogService sysOperLogService;



    // 配置织入点
    @Pointcut("@annotation(com.ly.common.annotation.Log)")
    public void logPointCut()
    {
    }
    @Before("logPointCut()")
    public  void dobefore(){
        log.info("====>切面之前会执行");
    }

    /**
     * 在代码执行之后,不论代码成功执行还是抛出异常都会执行到这里
     */
    @After("logPointCut()")
    public  void doAfter(){
        log.info("====>切面执行之后");
    }

    @AfterReturning(value = "logPointCut()",returning = "result")
    public  void AfterReturning(Object result){
        log.info("====>执行结果返回值:"+result.toString() );
    }


    /**
     * 前置通知 用于拦截操作
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()")
    public void doBefore(JoinPoint joinPoint)
    {
        handleLog(joinPoint, null);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfter(JoinPoint joinPoint, Exception e)
    {
        handleLog(joinPoint, e);
    }


    protected void handleLog(final JoinPoint joinPoint, final Exception e)
    {
        try
        {
            // 获得注解
            Log controllerLog = getAnnotationLog(joinPoint);
            if (controllerLog == null)
            {
                return;
            }

            // 获取当前的用户
            //SysUser currentUser = ShiroUtils.getUser();

            // *========数据库日志=========*//
            SysOperLog operLog = new SysOperLog();
            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
            // 请求的地址
            String ip = "192.168.24.63";
            operLog.setOperIp(ip);

            operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
            operLog.setOperName("liyu");
//            if (currentUser != null)
//            {
//                operLog.setOperName(currentUser.getLoginName());
//                if (StringUtils.isNotNull(currentUser.getDept())
//                        && StringUtils.isNotEmpty(currentUser.getDept().getDeptName()))
//                {
//                    operLog.setDeptName(currentUser.getDept().getDeptName());
//                }
//            }

            if (e != null)
            {
                operLog.setStatus(BusinessStatus.FAIL.ordinal());
                operLog.setErrorMsg(e.getMessage().toString());
            }
            // 设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            operLog.setMethod(className + "." + methodName + "()");
            // 处理设置注解上的参数
            getControllerMethodDescription(controllerLog, operLog);
            // 保存数据库
           // AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
            sysOperLogService.insertSysOperLog(operLog);
        }
        catch (Exception exp)
        {
            // 记录本地异常日志
            log.error("==LogAspect异常==");
            log.error("异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
    }

    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @param log 切点
     * @return 方法描述
     * @throws Exception
     */
    public void getControllerMethodDescription(Log log, SysOperLog operLog) throws Exception
    {
        // 设置action动作
        operLog.setBusinessType(log.businessType().ordinal());
        // 设置标题
        operLog.setTitle(log.title());
        // 设置操作人类别
        operLog.setOperatorType(log.operatorType().ordinal());
        // 是否需要保存request,参数和值
        if (log.isSaveRequestData())
        {
            // 获取参数的信息,传入到数据库中。
            setRequestParam(operLog);
        }
    }

    /**
     * 获取请求的参数,放到SysOperLog中
     *
     * @param operLog 操作日志
     * @throws Exception 异常
     */
    private void setRequestParam(SysOperLog operLog) throws Exception
    {
        Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
        String params = JsonUtils.ObjToJsonStr(map);
        int len=params.length();
        operLog.setOperParam(params);
    }

    /**
     * 是否存在注解,如果存在就获取
     */
    private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
    {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null)
        {
            return method.getAnnotation(Log.class);
        }
        return null;
    }


}
   /**
 * 列表
 */
    @Log(title = "文章列表", businessType = BusinessType.INSERT)
    @RequestMapping("/list")

    public String list(@RequestParam(defaultValue = "1") int page  ,@RequestParam(defaultValue = "10") int limit,ModelMap mmap){

        Map<String,Object> params = new HashMap<String,Object>();
        params.put("page",page);
        params.put("limit",limit);
        Query query = new Query(params);
        List<Article> list = articleService.queryList(query);
        mmap.addAttribute("articles",list);

        return "/article/articleList";
    }

访问上图的api,注意:假如你的注解

@Log(title = "文章列表", businessType = BusinessType.INSERT)和LogAspect不在同一个项目或者同一个包,有可能上面的注解语句失效,调试的时候进入不了LogAspect,那是因为程序没有扫描到你的切面类,处理方法是在启动类里面添加logAspect所在的包的的路径,代码如下
package com.ly.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.ly.*")
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springboot整合AOP,实现log操作日志 的相关文章

随机推荐

  • pycharm利用快捷键,快速注释多行代码的方法分享

    最近在pycharm的新手学习群里 发现有些小伙伴依然在 手工 进行代码的注释 效率较低 下面分享pycharm利用快捷键 快速注释多行代码的方法 可以帮助pycharm初学者加倍提升代码的注释效率 代码注释快捷键 pycharm代码注释的
  • springboot动态数据源用shardingjdbc按时间分表

    1 背景 原有项目架构 springboot mybatis plus dynamic datasource 动态数据源 mybatis plus拓展 druid 连接池 根据业务数据不断增加 需要进行对业务量大的数据表行分表 因为以前的业
  • nacos注册中心面试总结

    1注册中心演变及其设计思想 2 Nacos注册中心架构 3 核心功能 服务注册 Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务 提供自身的元数据 比如ip地址 端口等信息 Nacos Serve
  • jps 命令

    NAME jps Lists the instrumented Java Virtual Machines JVMs on the target system This command is experimental and unsuppo
  • 【Pytorch】第 3 章 :进行数值估计的蒙特卡洛方法

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • 芯片跨时钟域同步,即异步处理的理解

    网上有一套资料Clifford E Cummings论文合集 还不错 以下是临时想到的 亚稳态就是时序违反的后果 异步信号肯定有时序违反可能 单bit 源时钟域打一拍 目的时钟域打两拍或者更多拍 多bit fifo方法 原理是格雷码指针判断
  • 《机器学习实战》——第13章 利用PCA来简化数据

    在低维下 数据更容易进行处理 其相关特征可能在数据中明确地显示出来 通常而言 我们再应用其他机器学习算法之前 必须先识别出其相关特征 13 1 降维技术 始终贯穿本书的一个难题就是对数据和结果的展示 这是因为文字图像是二维的 而在通常情况下
  • Uniyt热更新——LuaFrameWork学习(三)判断unity里对象为空

    在游戏制作过程中我们经常会Destroy一些没用的GameObject 那么在ulua里我们怎么样来判断我们的引用被Destroy了呢 这里要感谢阿盟哥 他已经为我们解决了这个问题 在他写的 Global lua里 代码如下 functio
  • 第二章 使用HTML标签组织页面内容

    前言 使用VS Code进行一系列的实操 跟着学习 一起进步 这章大部分代码注释都在代码段里边 需要点开查阅 作者希望和大家一起探讨 不断吸取经验 感谢鼓励 之后还会有有关CSS JavaScript JQuery等的更新 欢迎关注收藏订阅
  • VUE element-ui 之table表格第一行插入输入框

    步骤 模板中配置列
  • typescript在vue3中的使用。

    1 项目安装typescript 我在创建项目时就选择了安装typescript 如果创建vue3项目时并没有安装typescript依赖 也可以用命令行安装 执行如下命令 npm install typescript save dev 2
  • DNSPod十问黄欢:为什么互联网大厂都要去造车?

    荆虹科技创始人 3D TOF视觉领域专家 六西格玛黑带大师 天津大学工业工程硕士 曾就职于台湾扬信与盛泰光学 领导并服务过Moto Nokia 苹果手机摄像头项目 人称奶罩 腾讯云中小企业中心总经理 DNSPod创始人 洋葱令牌创始人 网络
  • 有一个含n(n」2)个整数的数组a,判断其中是否存在出现次数超过所有元素一半的元素

    一 问题描述 有一个含n n gt 2 个整数的数组a 判断其中是否存在出现次数超过所有元素一半的元素 二 问题分析与解答 分析 可以先将数组a中的元素递增排序 再求出出现次数最多的次数maxnum 最后判断是否满足条件 代码实现 incl
  • 【CV】第 5 章:神经网络架构和模型

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • unity3d 学习笔记(二)

    AudioClip 声音资源的使用 unity3d中声音资源可以设置为3d音效或者2d音效 3d音效受空间的影响 越近声音越大 component Audio source 声音的发生物体 Audio listener 声音的接受者 一般放
  • Unity3D循环滚动的背景图片?制作方法!!!!

    链接 http momowing diandian com post 2013 01 26 40049505995 真是抱歉 从今天起才认真的翻阅android game example 这个插件 开始熟悉一下外国佬的一些编程方式 相信很多
  • Redis事务详述,java百度人脸识别

    1 简介 Redis类似大多数成熟的数据库系统一样 提供了事务机制 Redis的事务机制非常简单 它没有严格的事务模型 无法像关系型数据库一样保证操作的原子性 Redis事务最大的作用是保证多个指令的串行执行 它可以借助于Redis单线程读
  • .获取MAC地址方法大全

    Windows平台下用C 代码取得机器的MAC地址并不是一件简单直接的事情 到目前为止 作者尚未发现有任何一个通用的100 的适用于所有Windows平台的方法可以稳定的取得MAC地址 而有些应用 比如MMORPG 则需要稳定的得到机器的M
  • scrapy-redis报错:spop() takes 2 positional arguments but 3 were given

    Scrapy Redis报错 spop takes 2 positional arguments but 3 were given 解决之旅 大家好 在这篇博客中 我们将一起探讨如何解决在使用Scrapy Redis时遇到的一个常见报错问题
  • springboot整合AOP,实现log操作日志

    添加依赖