spring aop 自定义注解配合swagger注解保存操作日志到mysql数据库含(源码)

一、思路

利用spring aop 对方法进行增强,获取用户操作的各种信息。

二、自定义注解

/**
 * 操作日志注解
 *
 * @author chenjiayan
 * @date 2022/12/21
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OptLog {
    
    

    /**
     * @return 操作类型
     */
    String optType() default "";

}

三、编写操作日志

包括实体类,service,mapper等,这里就不再过多赘述

操作日志实体类 仅供参考

/**
 * <p>
 * 操作日志
 * </p>
 *
 * @author chenjiayan
 * @since 2022-12-21
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("tb_operation_log")
@ApiModel(value="OperationLog对象", description="")
public class OperationLog implements Serializable {
    
    

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "日志id")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @ApiModelProperty(value = "操作模块")
    private String optModule;

    @ApiModelProperty(value = "操作类型")
    private String optType;

    @ApiModelProperty(value = "操作url")
    private String optUrl;

    @ApiModelProperty(value = "操作方法")
    private String optMethod;

    @ApiModelProperty(value = "操作描述")
    private String optDesc;

    @ApiModelProperty(value = "请求参数")
    private String requestParam;

    @ApiModelProperty(value = "请求方式")
    private String requestMethod;

    @ApiModelProperty(value = "返回数据")
    private String responseData;

    @ApiModelProperty(value = "用户id")
    private Integer userId;

    @ApiModelProperty(value = "用户昵称")
    private String nickname;

    @ApiModelProperty(value = "操作ip")
    private String ipAddress;

    @ApiModelProperty(value = "操作地址")
    private String ipSource;

    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    @ApiModelProperty(value = "更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
}

service和mapper我就不写了,请自行编写。

四、编写操作日志切面\增强

这里运用到了swagger的相关注解,不了解的可以先去学习一下,比较简单

/**
 * 操作日志切面处理
 * chenjiayan
 * 2022/12/21
 */
@Aspect
@Component
public class OptLongAspect {
    
    
    @Autowired
    private OperationLogService operationLogService = new OperationLogServiceImpl();

    /**
     * 设置操作日志切入点 记录操作日志 在注解的位置切入代码
     */
    @Pointcut("@annotation(fit.littlefox.blog.annotation.OptLog)")
    public void optLogPointCut(){
    
    }

    @AfterReturning(value = "optLogPointCut()",returning = "keys")
    public void saveOptLog(JoinPoint joinPoint,Object keys){
    
    
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) Objects.requireNonNull(requestAttributes).resolveReference(RequestAttributes.REFERENCE_REQUEST);
        OperationLog operationLog = new OperationLog();
        // 从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取切入点所在的方法
        Method method = signature.getMethod();
        // 获取操作(类上的注解)
        Api api = (Api) signature.getDeclaringType().getAnnotation(Api.class);
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        OptLog optLog = method.getAnnotation(OptLog.class);
        // 操作模块
        operationLog.setOptModule(api.tags()[0]);
        // 操作类型 (增删改查)
        operationLog.setOptType(optLog.optType());
        // 操作url
        operationLog.setOptUrl(request.getRequestURI());
        // 操作方法
        // 1.获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        // 2.获取请求的方法名
        String methodName = method.getName();
        methodName = className+"."+methodName;
        operationLog.setOptMethod(methodName);
        // 操作描述
        operationLog.setOptDesc(apiOperation.value());
        // 请求参数
        operationLog.setRequestParam(JSON.toJSONString(joinPoint.getArgs()));
        // 请求方式(GET,POST,PUT...)
        operationLog.setRequestMethod(Objects.requireNonNull(request).getMethod());
        // 返回数据
        operationLog.setResponseData(JSON.toJSONString(keys));
        // 操作用户id
        operationLog.setUserId(UserUtils.getLoginUser().getId());
        // 操作用户昵称
        operationLog.setNickname(UserUtils.getLoginUser().getNickname());
        // 操作/请求 ip
        String ipAddress = IpUtils.getIpAddress(request);
        operationLog.setIpAddress(ipAddress);
        // 操作/请求 地址
        operationLog.setIpSource(IpUtils.getIpSource(ipAddress));

        // 保存
        operationLogService.save(operationLog);
    }

}

五、使用

编写完上述代码,使用就非常简单了,只需在想要记录操作日志的方法上添加自定义的注解(@OptLog(“操作类型”))就行了

例如:

    /**
     * 添加或修改文章
     *
     * @param articleVO 文章信息
     * @return {@link Result<>}
     */
    @OptLog(optType = SAVE_OR_UPDATE)
    @ApiOperation(value = "添加或修改文章")
    @PostMapping("/admin/articles")
    public Result<?> saveOrUpdateArticle(@Valid @RequestBody ArticleVO articleVO) {
    
    
        articleService.saveOrUpdateArticle(articleVO);
        return Result.ok();
    }

六、注意

上述代码用到了很多工具类(IpUtils用来解析ip的工具类、UserUtils用来获取用户信息的工具类),这里就不再提供了,可以根据自己的情况编写或者在网上进行搜索。
总之,上述代码只是教你如何使用 spring aop 自定义注解保存操作日志到mysql数据库,具体的很多地方都可以根据自己的情况进行添加修改。

猜你喜欢

转载自blog.csdn.net/weixin_52067659/article/details/128409729