iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >怎么使用Aop的方式实现自动日志记录
  • 546
分享到

怎么使用Aop的方式实现自动日志记录

2023-06-30 08:06:21 546人浏览 独家记忆
摘要

本篇内容介绍了“怎么使用aop的方式实现自动日志记录”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用Aop的方式实现自动日志记录自动日志记

本篇内容介绍了“怎么使用aop的方式实现自动日志记录”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

使用Aop的方式实现自动日志记录

自动日志记录的实现的两种方式:

①通过监听器去监听,当访问到具体的类方法,通过aop切面去获取访问的方法,然后将日志记录下来
②通过拦截器,编写一个类去继承HandlerInterceptorAdapter,重写preHandle,postHandle,然后在里面进行日志记录,编写的类加到spring容器

采用第一种方式:

1、第一步、定义一个注解:

Annotation 注解的作用:

@interface 表示这是一个注解类, 不是interface,是注解类 定义注解用的,是jdk1.5之后加入的,java没有给它新的关键字,所以就用@interface 这么个东西表示了

@Inherited //这个Annotation 可以被继承

@Documented //这个Annotation可以被写入javadoc

@Target:注解的作用目标

@Target(ElementType.TYPE) //接口、类、枚举、注解
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包

@Retention(RetentionPolicy.RUNTIME) //可以用来修饰注解,是注解的注解,称为元注解。

public enum RetentionPolicy {       SOURCE, // 编译器处理完Annotation后不存储在class中       CLASS, // 编译器把Annotation存储在class中,这是默认值       RUNTIME // 编译器把Annotation存储在class中,可以由虚拟机读取,反射需要   }

创建一个注解:

default 0 相当于set和get方法,添加一个默认值

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface AutoLog {String value() default ""; * 日志类型 * @return 1:登录日志;2:操作日志;3:访问日志;4:异常日志;5:定时任务;int logType() default CommonConstant.LOG_TYPE_2; * 操作日志类型 * @return (1查询,2添加,3修改,4删除)int operateType() default 0;}

CommonConstant 相关的配置

public interface CommonConstant {public static final Integer STATUS_NORMAL = 0; * 禁用状态public static final Integer STATUS_DISABLE = -1; * 删除标志public static final Integer DEL_FLAG_DELETED = 1; * 未删除public static final Integer DEL_FLAG_UNDELETED = 0; * 系统日志类型: 登录public static final int LOG_TYPE_1 = 1; * 系统日志类型: 操作public static final int LOG_TYPE_2 = 2;    public static final int LOG_TYPE_3 = 3;     * 系统日志类型: 异常    public static final int LOG_TYPE_4 = 4;     * 系统日志类型: 定时任务    public static final int LOG_TYPE_5 = 5;     * 系统日志类型: 用户管理    public static final int LOG_TYPE_6 = 6;     * 系统登陆日志:正常账户密码登录    public static final int OPERATE_TYPE_LT1_1 = 1;     * 系统登陆日志:二维码登陆    public static final int OPERATE_TYPE_LT1_2 = 2;     * 系统登陆日志:单点登陆    public static final int OPERATE_TYPE_LT1_3 = 3;     * 系统登陆日志:登出    public static final int OPERATE_TYPE_LT1_4 = 4;     * 系统登陆日志:模拟登陆    public static final int OPERATE_TYPE_LT1_5 = 5; * 操作日志类型: 查询public static final int OPERATE_TYPE_LT2_1 = 1; * 操作日志类型: 添加public static final int OPERATE_TYPE_LT2_2 = 2; * 操作日志类型: 更新public static final int OPERATE_TYPE_LT2_3 = 3; * 操作日志类型: 删除public static final int OPERATE_TYPE_LT2_4 = 4; * 操作日志类型: 导入public static final int OPERATE_TYPE_LT2_5 = 5; * 操作日志类型: 导出public static final int OPERATE_TYPE_LT2_6 = 6;     * 访问日志类型: 进入    public static final int OPERATE_TYPE_LT3_1 = 1;     * 异常日志类型: 普通操作即代码错误    public static final int OPERATE_TYPE_LT4_1 = 1;     * 异常日志类型: 非法操作即越权操作    public static final int OPERATE_TYPE_LT4_2 = 2;public static final String CLIENT_TYPE_PC="0";public static final String CLIENT_TYPE_MOBILE="1";    public static final Integer SC_INTERNAL_SERVER_ERROR_500 = 500;        public static final Integer SC_OK_200 = 200;            public static final Integer SC_JEECG_NO_AUTHZ=510;        public static String PREFIX_USER_shiro_CACHE  = "shiro:cache:org.jeecg.modules.shiro.authc.ShiroRealm.authorizationCache:";        public static final String PREFIX_USER_TOKEN  = "prefix_user_token_";        public static final int  TOKEN_EXPIRE_TIME  = 3600;     *  0:一级菜单    public static final Integer MENU_TYPE_0  = 0;       public static final Integer MENU_TYPE_1  = 1;     *  2:按钮权限    public static final Integer MENU_TYPE_2  = 2;        public static final String MSG_TYPE_UESR  = "USER";    public static final String MSG_TYPE_ALL  = "ALL";        public static final String NO_SEND  = "0";    public static final String HAS_SEND  = "1";    public static final String HAS_CANCLE  = "2";        public static final String HAS_READ_FLAG  = "1";    public static final String NO_READ_FLAG  = "0";        public static final String PRIORITY_L  = "L";    public static final String PRIORITY_M  = "M";    public static final String PRIORITY_H  = "H";     * 短信模板方式  0 .登录模板、1.注册模板、2.忘记密码模板    public static final String SMS_TPL_TYPE_0  = "0";    public static final String SMS_TPL_TYPE_1  = "1";    public static final String SMS_TPL_TYPE_2  = "2";     * 状态(0无效1有效)    public static final String STATUS_0 = "0";    public static final String STATUS_1 = "1";     * 同步工作流引擎1同步0不同步    public static final String ACT_SYNC_0 = "0";    public static final String ACT_SYNC_1 = "1";     * 消息类型1:通知公告2:系统消息    public static final String MSG_CATEGoRY_1 = "1";    public static final String MSG_CATEGORY_2 = "2";     * 是否配置菜单的数据权限 1是0否    public static final Integer RULE_FLAG_0 = 0;    public static final Integer RULE_FLAG_1 = 1;     * 用户状态 0冻结 1正常 2待定    public static final Integer USER_FREEZE = 0;    public static final Integer USER_NORMAL = 1;     * 用户删除标志位 0未删 1已删    public static final Integer USER_DELETE_NO=0;    public static final Integer USER_DELETE_YES=1;        public static final String DICT_TEXT_SUFFIX = "_dictText";    public static final String ITEM_DISPLAY = "_display";     * 表单设计器主表类型    public static final Integer DESIGN_FORM_TYPE_MaiN = 1;     * 表单设计器子表表类型    public static final Integer DESIGN_FORM_TYPE_SUB = 2;     * 表单设计器URL授权通过    public static final Integer DESIGN_FORM_URL_STATUS_PASSED = 1;     * 表单设计器URL授权未通过    public static final Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2;     * 表单设计器新增 Flag    public static final String DESIGN_FORM_URL_TYPE_ADD = "add";     * 表单设计器修改 Flag    public static final String DESIGN_FORM_URL_TYPE_EDIT = "edit";     * 表单设计器详情 Flag    public static final String DESIGN_FORM_URL_TYPE_DETAIL = "detail";     * 表单设计器复用数据 Flag    public static final String DESIGN_FORM_URL_TYPE_REUSE = "reuse";     * 表单设计器编辑 Flag (已弃用)    public static final String DESIGN_FORM_URL_TYPE_VIEW = "view";     * online参数值设置(是:Y, 否:N)    public static final String ONLINE_PARAM_VAL_IS_TURE = "Y";    public static final String ONLINE_PARAM_VAL_IS_FALSE = "N";     * 文件上传类型(本地:local,MiNIO:minio,阿里云:aliOSs)    public static final String UPLOAD_TYPE_LOCAL = "local";    public static final String UPLOAD_TYPE_MINIO = "minio";    public static final String UPLOAD_TYPE_OSS = "alioss";     * 员工身份 (1:普通员工  2:上级)    public static final Integer USER_IDENTITY_1 = 1;    public static final Integer USER_IDENTITY_2 = 2;     * 日期格式    public static final String TIME_FORMAT_YMD = "yyyy-MM-dd";    public static final String TIME_FORMAT_YMDHMS = "yyyy-MM-dd HH:mm:ss";    public static final String TIME_FORMAT_YMDHMSSZ = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";}

2、第二步、编写一个切面

@Aspect 表示这是一个切面

@Component 告诉spring 这是一个bean ,注入

@annotation 获取定义的注解

@Pointcut 切点,

@Pointcut("@annotation(xx.AutoLog)") 表示,使用了这个注解的,就是切入点

@Around的作用

既可以在目标方法之前织入增强动作,也可以在执行目标方法之后织入增强动作;
可以决定目标方法在什么时候执行,如何执行,甚至可以完全阻止目标目标方法的执行;
可以改变执行目标方法的参数值,也可以改变执行目标方法之后的返回值; 当需要改变目标方法的返回值时,只能使用Around方法;
虽然Around功能强大,但通常需要在线程安全的环境下使用。因此,如果使用普通的Before、AfterReturing增强方法就可以解决的事情,就没有必要使用Around增强处理了。

ProceedingJoinPoint 环绕通知,主要作用找到程序执行中的可识别的点,当aop的切入点

  1. 环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。

  2. 简单理解,环绕通知=前置+目标方法执行+后置通知,proceed方法就是用于启动目标方法执行的.

@Aspect@Componentpublic class AutoLogAspect {    @Autowired    private ISysLogService sysLogService;    @Pointcut("@annotation(xx.AutoLog)")    public void logPointCut() {    }    @Around("logPointCut()")    public Object around(ProceedingJoinPoint point) throws Throwable {        long beginTime = System.currentTimeMillis();        //执行方法        Object result = point.proceed();        //执行时长(毫秒)        long time = System.currentTimeMillis() - beginTime;        //保存日志        saveSysLog(point, time);        return result;    }    private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {        MethodSignature signature = (MethodSignature) joinPoint.getSignature();        Method method = signature.getMethod();        SysLog sysLog = new SysLog();        AutoLog syslog = method.getAnnotation(AutoLog.class);        if (syslog != null) {            //注解上的描述,操作日志内容            sysLog.setLoGContent(syslog.value());            sysLog.setLogType(syslog.logType());        }        //请求的方法名        String className = joinPoint.getTarget().getClass().getName();        String methodName = signature.getName();        sysLog.setMethod(className + "." + methodName + "()");        //设置操作类型        if (sysLog.getLogType() == CommonConstant.LOG_TYPE_2) {            sysLog.setOperateType(getOperateType(methodName, syslog.operateType()));        }        //请求的参数        Object[] args = joinPoint.getArgs();        try {            String params = JSONObject.tojsONString(args);            sysLog.setRequestParam(params);        } catch (Exception e) {        }        try {            //获取request            httpservletRequest request = SpringContextUtils.getHttpServletRequest();            //设置IP地址            sysLog.setIp(IPUtils.getIpAddr(request));        } catch (Exception e) {        }        //获取登录用户信息        LoginUser sysUser = null;        try {            sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();        } catch (Exception e) {        }        if (sysUser != null) {            sysLog.setUserId(sysUser.getId());            sysLog.setUserName(sysUser.getUserName());            sysLog.setRealName(sysUser.getRealName());            sysLog.setOrgId(sysUser.getNowOrgId());            sysLog.setOrgName(sysUser.getNowOrgName());        }        //耗时        sysLog.setCostTime(time);        sysLog.setCreateTime(new Date());        //保存系统日志        sysLogService.save(sysLog);    }        private int getOperateType(String methodName, int operateType) {        if (operateType > 0) {            return operateType;        }        if (methodName.startsWith("list")) {            return CommonConstant.OPERATE_TYPE_LT2_1;        }        if (methodName.startsWith("add")) {            return CommonConstant.OPERATE_TYPE_LT2_2;        }        if (methodName.startsWith("edit")) {            return CommonConstant.OPERATE_TYPE_LT2_3;        }        if (methodName.startsWith("delete")) {            return CommonConstant.OPERATE_TYPE_LT2_4;        }        if (methodName.startsWith("import")) {            return CommonConstant.OPERATE_TYPE_LT2_5;        }        if (methodName.startsWith("export")) {            return CommonConstant.OPERATE_TYPE_LT2_6;        }        return CommonConstant.OPERATE_TYPE_LT2_1;    }    @AfterThrowing(pointcut = "logPointCut()", throwing = "ex")    public void afterThrowing(JoinPoint joinPoint, Throwable ex) {        MethodSignature signature = (MethodSignature) joinPoint.getSignature();        Method method = signature.getMethod();        SysLog sysLog = new SysLog();        StackTraceElement[] stackTraceElements = ex.getStackTrace();        String rootExceptionName = ex.getClass().getName();        StringBuilder resultContent = new StringBuilder("异常类:" + rootExceptionName);        int count = 0;        int maxTrace = 3;        for (StackTraceElement stackTraceElement : stackTraceElements) {            if (stackTraceElement.getClassName().contains("com.lingxu") && count < maxTrace) {                resultContent.append("\n出现于").append(stackTraceElement.getClassName())                        .append("类中的").append(stackTraceElement.getMethodName())                        .append("方法中 位于该类文件的第").append(stackTraceElement.getLineNumber())                        .append("行)");                count++;                if (count == maxTrace) {                    break;                }            }        }        sysLog.setExceptionContent(resultContent.toString());        AutoLog syslog = method.getAnnotation(AutoLog.class);        if (syslog != null) {            //注解上的描述,操作日志内容            sysLog.setLogContent(syslog.value() + "出现异常");            sysLog.setLogType(CommonConstant.LOG_TYPE_4);        }        //请求的方法名        String className = joinPoint.getTarget().getClass().getName();        String methodName = signature.getName();        sysLog.setMethod(className + "." + methodName + "()");        //设置操作类型        sysLog.setOperateType(CommonConstant.OPERATE_TYPE_LT4_1);        //请求的参数        Object[] args = joinPoint.getArgs();        try {            String params = JSONObject.toJSONString(args);            sysLog.setRequestParam(params);        } catch (Exception e) {        }        try {            //获取request            HttpServletRequest request = SpringContextUtils.getHttpServletRequest();            //设置IP地址            sysLog.setIp(IPUtils.getIpAddr(request));        } catch (Exception e) {        }        try {            //获取登录用户信息            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();            if (sysUser != null) {                sysLog.setUserId(sysUser.getId());                sysLog.setUserName(sysUser.getUserName());                sysLog.setRealName(sysUser.getRealName());                sysLog.setOrgId(sysUser.getNowOrgId());                sysLog.setOrgName(sysUser.getNowOrgName());            }        } catch (Exception e) {        }        //保存系统日志        sysLogService.save(sysLog);    }}

3、使用自定义注解

可以在controller或者实现类上进行注解的加入

怎么使用Aop的方式实现自动日志记录

@AutoLog(value = "sss",logType = CommonConstant.LOG_TYPE_3, operateType = 2)@apiOperation(value="记录查询日志-分页列表查询", notes="记录查询日志-分页列表查询")@PostMapping(value = "/queryPage")public Result<?> queryPage(@RequestBody SysSelectLog sysSelectLog){Page<SysSelectLog> page = new Page<>(sysSelectLog.getPageNo(),sysSelectLog.getPageSize());IPage<SysSelectLog> sysSelectLogIPage = sysSelectLogService.queryPage(page,sysSelectLog);return Result.ok(sysSelectLogIPage);}

“怎么使用Aop的方式实现自动日志记录”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 怎么使用Aop的方式实现自动日志记录

本文链接: https://www.lsjlt.com/news/327727.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么使用Aop的方式实现自动日志记录
    本篇内容介绍了“怎么使用Aop的方式实现自动日志记录”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用Aop的方式实现自动日志记录自动日志记...
    99+
    2023-06-30
  • 使用Aop的方式实现自动日志记录的方式详细介绍
    目录34、使用Aop的方式实现自动日志记录采用第一种方式:1、第一步、定义一个注解:2、第二步、编写一个切面3、使用自定义注解34、使用Aop的方式实现自动日志记录 自动日志记录的实...
    99+
    2024-04-02
  • SpringBoot开发怎么使用AOP记录日志
    这篇文章主要讲解了“SpringBoot开发怎么使用AOP记录日志”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringBoot开发怎么使用AOP记录日志”吧!为什么要用AOP?答案是解...
    99+
    2023-06-25
  • 运用Spring Aop+注解实现日志记录
    目录1. 介绍2. 实践2.1 定义注解2.2 切面类2.3 编写测试方法2.4 运行结果3. 总结4. 参考文章1. 介绍 我们都知道Spring框架的两大特性分别是 IOC (控...
    99+
    2024-04-02
  • 使用SpringBoot AOP 记录操作日志、异常日志的过程
    平时我们在做项目时经常需要对一些重要功能操作记录日志,方便以后跟踪是谁在操作此功能;我们在操作某些功能时也有可能会发生异常,但是每次发生异常要定位原因我们都要到服务器去查询日志才能找...
    99+
    2024-04-02
  • SpringBoot使用AOP记录接口操作日志的方法
    目录一、操作日志简介1.1、系统日志和操作日志的区别1.2、操作日志记录实现方式二、AOP面向切面编程2.1、AOP简介2.2、AOP作用2.3、AOP相关术语2.4、JointPo...
    99+
    2022-11-13
    SpringBoot AOP记录接口 SpringBoot AOP操作日志
  • Spring AOP实现复杂的日志记录操作(自定义注解)
    目录Spring AOP复杂的日志记录(自定义注解)第一步第二步第三步第四步多个注解可以合并成一个,包括自定义注解比如说SpringMVC的注解Spring AOP复杂的日志记录(自...
    99+
    2024-04-02
  • 在springboot中怎么使用AOP进行全局日志记录
    小编给大家分享一下在springboot中怎么使用AOP进行全局日志记录,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!1、 spring AOP 是什么?spring 的两大核心就是 IOC 和 AOP,AOP 是 spr...
    99+
    2023-06-21
  • python怎么实现记录用户登录日志
    本篇内容主要讲解“python怎么实现记录用户登录日志”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“python怎么实现记录用户登录日志”吧!任务1、记录用户登录日志import ti...
    99+
    2023-06-29
  • SpringBoot中怎么实现日志记录
    在SpringBoot中,可以通过使用Logback、Log4J、Log4J2等日志框架来实现日志记录。一般来说,SpringBoo...
    99+
    2024-03-07
    SpringBoot
  • Java日志记录的新方式:使用Spring和Bash
    在Java应用程序中,日志记录是非常重要的一部分。它可以帮助我们追踪应用程序的行为、问题和异常情况。传统的日志记录方式是通过Java自带的log4j、logback等框架进行记录,但是这些框架的日志记录方式有时候会比较繁琐和复杂。本文将介...
    99+
    2023-06-21
    日志 spring bash
  • 利用spring AOP记录用户操作日志的方法示例
    前言最近项目已经开发完成,但发现需要加用户操作日志,如果返回去加也不太现实,所以使用springAOP来完成比较合适。下面来一起看看详细的介绍:注解工具类:@Retention(RetentionPolicy.RUNTIME)@Target...
    99+
    2023-05-31
    springaop 用户操作 日志记录
  • 如何使用ActionFilterAttribute实现API日志的记录
    本篇内容主要讲解“如何使用ActionFilterAttribute实现API日志的记录”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何使用ActionFil...
    99+
    2024-04-02
  • springboot使用自定义注解实现aop切面日志
    平时我们在开发过程中,代码出现bug时为了更好的在服务器日志中寻找问题根源,会在接口的首尾打印日志,看下参数和返回值是否有问题。但是手动的logger.info() 去编写时工作量较...
    99+
    2024-04-02
  • ASP.NETCore使用Log4net实现日志记录功能
    一、安装Log4net 1、使用Nuget包进行安装 在依赖项上面右键,选择“管理NuGet程序包”,如下图所示: 在浏览界面输入log4net,然后点击安...
    99+
    2024-04-02
  • 使用Spring MVC拦截器实现日志记录的方法
    最近在研究Spring MVC拦截器,那么今天也算个学习笔记吧!有需要了解使用Spring MVC拦截器实现日志记录的朋友可参考。希望此文章对各位有所帮助。  定义一个类实现HandlerInterceptor,比如: ...
    99+
    2023-05-31
    springmvc 拦截器
  • golang xorm 自定义日志记录器之使用zap实现日志输出、切割日志(最新)
    目录1.准备并下载好需要的包2. 连接postgresql数据库3. zap日志工具4.实现xorm 自定义日志记录器5.使用完整代码参考文档1.准备并下载好需要的包 xorm.io...
    99+
    2024-04-02
  • Springboot中Aspect切面的实现方式(以记录日志为例)
    Springboot Aspect切面的实现 今天我们来说说spring中的切面Aspect,这是Spring的一大优势。面向切面编程往往让我们的开发更加低耦合,也大大减少了代码量,...
    99+
    2024-04-02
  • 使用java注解和aspectj AOP怎么实现打印日志
    本篇文章给大家分享的是有关使用java注解和aspectj AOP怎么实现打印日志,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。首先需要自定义注解:systemName:表示该...
    99+
    2023-06-06
  • Springboot使用slf4j记录日志的方法步骤
    目录前言如何在Springboot中使用slf4j记录日志测试前言 在项目开发中,记录日志是必做的一件事情。而当我们使用Springboot框架时,记录日志就变得极其简单了。 spr...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作