自定义注解 + AOP 记录用户的使用日志

自定义注解 + AOP 记录用户的使用日志

使用背景

(1)在学校项目中,安防平台实际的使用人员大多都是外聘人员,用户的一些关键操作最好记录清楚,像是青岛工程职业学院网络及监控系统项目中,有个功能是对全校学生权限的一键冻结和解冻。

(2)对接非常强势的第三方数据时,例如腾讯的腾讯微卡产品,虽然是他们将数据接入到海康平台,但仍然不接受定制,我们必须按照腾讯的接口协议,提供给他们接口。注意:此时没有办法走OpenApi,而请假数据是每天有推送的,为了一旦出现问题可回溯,需要记录完整的数据日志。

落地实践

一:自定义注解

配置自定义注解"LogPoint",之后会用在关键的接口上,作为切入点来记录该接口的访问信息。

java 复制代码
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface LogPoint {
    /***
    * @Description 日志描述
    * @return java.lang.String
    */
    String description() default "";
}

二:切面配置

1.在切面里,我们可以配置请求参数的详细信息逐条打印,和响应结果与它的耗时记录,这些打印信息足以应对现场的大多数问题。

2.不用担心info日志打印过多的问题,只需要把注解标注在关键的接口,与多占的那些硬盘空间相比,这些信息能帮助技术和研发节省更多的时间,更具性价比。

java 复制代码
    
    /**
     * @ClassName AspectLogConfig
     * @Description 出入参日志配置类
     * @Version 1.0
     **/
    @Aspect
    @Component
    @Slf4j
    public class LogConfig {
        private final static Logger logger = LoggerFactory.getLogger(LogConfig.class);
    
        @Pointcut("@annotation(com.hikvision.pea.common.annotation.LogPoint)")
        public void logPoint() {
        }
    
        /***
         * @Description 切入点之前织入
         * @Param []
         * @return void
         */
        @Before("logPoint()")
        public void doBefore(JoinPoint joinPoint) throws Throwable {
            //开始打印请求日志
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
    
            //打印请求相关参数
            logger.info("================== start ==================");
    
            //打印请求 url
            logger.info("URL              : {}", request.getRequestURL().toString());
            //打印描述信息
    
            //打印HTTP method
            logger.info("HTTP Method      : {}", request.getMethod());
            //打印调用 controller 的全路径以及执行方法
            logger.info("Class Method     : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
            //打印请求的ip
            logger.info("IP               : {}", request.getRemoteAddr());
            //打印请求入参
            logger.info("Request Args     : {}", joinPoint.getArgs());
        }
    
        @After("logPoint()")
        public void doAfter() throws Throwable {
    
        }
    
        /***
         * @Description 环绕
         * @Date 14:35 2022/6/23
         * @Param [proceedingJoinPoint]
         * @return java.lang.Object
         */
        @Around("logPoint()")
        public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            long startTime = System.currentTimeMillis();
            //执行切点
            Object result = proceedingJoinPoint.proceed();
            logger.info("打印出参 : {}", result);
            logger.info("执行耗时 : {} ms", System.currentTimeMillis() - startTime);
            logger.info("================== end ===================" + System.lineSeparator());
            return result;
        }
    }

三:Api层使用

只需要将注解加在对应的接口上,无需其它编码。

java 复制代码
/**
 * @ClassName ResourceController
 * @Description 门禁点控制器
 * @Version 1.0
 **/

@Api(tags = "门禁点控制器")
@RestController
@RequestMapping("/resource")
@Slf4j
public class ResourceController {
    @Autowired
    IResourceService iResourceService;

    @ApiOperation("获取门禁点资源")
    @PostMapping("/doorSources")
    @LogPoint(description = "获取门禁点资源")
    public ResponseData getDoorSources(@ApiParam("入参") @RequestBody ResourceReqVo resourceReqVo) {
        Page<Resource> resources = iResourceService.getResources(resourceReqVo);
        return ResponseData.success(resources);
    }
}

使用效果

将调用方的请求参数、IP、响应结果、耗时,都完整的打印出来,一旦出现外聘人员误操作或者三方数据不匹配,通过这些信息,定位起问题来都非常方便。

相关推荐
程序员泠零澪回家种桔子15 分钟前
Spring AI框架全方位详解
java·人工智能·后端·spring·ai·架构
CodeCaptain23 分钟前
nacos-2.3.2-OEM与nacos3.1.x的差异分析
java·经验分享·nacos·springcloud
Anastasiozzzz1 小时前
Java Lambda 揭秘:从匿名内部类到底层原理的深度解析
java·开发语言
骇客野人1 小时前
通过脚本推送Docker镜像
java·docker·容器
铁蛋AI编程实战2 小时前
通义千问 3.5 Turbo GGUF 量化版本地部署教程:4G 显存即可运行,数据永不泄露
java·人工智能·python
晚霞的不甘2 小时前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频
SunnyDays10112 小时前
使用 Java 冻结 Excel 行和列:完整指南
java·冻结excel行和列
摇滚侠2 小时前
在 SpringBoot 项目中,开发工具使用 IDEA,.idea 目录下的文件需要提交吗
java·spring boot·intellij-idea
云姜.2 小时前
java多态
java·开发语言·c++
李堇2 小时前
android滚动列表VerticalRollingTextView
android·java