spring boot自定义注解AOP实现操作日志写入数据库

  • Post author:
  • Post category:其他


1:创建好要保存的实体类

package com.example.springboot.entity;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

import java.util.Date;

@Data
@ApiModel("操作日志实体类")
@Accessors(chain = true)
public class OperationLogEntity {

    @ApiModelProperty(value="请求记录")
    private String request;

    @ApiModelProperty(value="返回记录")
    private String response;

    @ApiModelProperty(value="操作人")
    private String logName;

    @ApiModelProperty(value="操作记录:1:新增 2:删除  3:修改 ")
    private String type;

    @ApiModelProperty(value="操作时间 ")
    private Date createDate;

    @ApiModelProperty(value="操作内容描述")
    private String content;

    @ApiModelProperty(value="接口名称")
    private String interfaceName;

}

二:自定义注解和要接收的字段

package com.example.springboot.annotation;

import java.lang.annotation.*;


/**
 * 用于记录操作日志
 */
@Target(value = ElementType.METHOD)//用于描述方法
@Retention(RetentionPolicy.RUNTIME)//注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
@Documented
public @interface OperationLog {

    //操作类型
    String logType() default "";

    //操作记录
    String content() default "";

    //操作人
    String operationName() default "";
}

三:编写aop切入

package com.example.springboot.config;

import com.alibaba.fastjson.JSON;
import com.example.springboot.annotation.OperationLog;
import com.example.springboot.entity.OperationLogEntity;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
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.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;

@Aspect
@Component
public class OperationLogAspect {


    /**
     * 定义切点
     *
     * @Pointcut 注解的所在路径
     */
    @Pointcut("@annotation(com.example.springboot.annotation.OperationLog)")
    public void logPointCut() {
    }


    @AfterReturning(value = "logPointCut() && @annotation(logger)", returning = "ret")
    public void saveOperationLog(JoinPoint joinPoint, OperationLog logger, Object ret) throws IOException {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //请求记录
        String s = JSON.toJSONString(joinPoint.getArgs());
        //创建一个操作日志实体类存放此次操作信息
        OperationLogEntity operationLog = new OperationLogEntity();
        //操作人
        operationLog.setLogName(logger.operationName());
        //请求json
        operationLog.setRequest(s);
        //操作内容描述
        operationLog.setContent(logger.content());
        //操作类型
        operationLog.setType(logger.logType());
        //操作时间
        operationLog.setCreateDate(new Date());
        //获取uri
        String requestURI = request.getRequestURI();
        //操作的url
        operationLog.setInterfaceName(requestURI);
        //若有返回结果,封装返回信息
        if (null != ret) {
            //响应内容
            operationLog.setResponse(ret.toString());
        }
        //将操作日志写入数据库
        System.out.println(operationLog);
    }
}

应为我这里没有写保存数据,只把实体类进行了输出。

四:将注解放在方法上

    @ApiOperation(value = "登陆")
    @PostMapping(value = "/login")
    @OperationLog(logType = "sign",operationName = "heqiang",content = "登录")
    public Result login(@RequestBody UserEntity user) {
        if (StringUtils.isNotBlank(user.getUserName()) && StringUtils.isNotBlank(user.getPassword())) {
                    try {
                        Subject subject = SecurityUtils.getSubject();
                        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUserName(), user.getPassword());
                subject.login(usernamePasswordToken);
            } catch (UnknownAccountException e) {
                return Result.error(CodeMsg.USERERROR, "账号不存在");
            } catch (LockedAccountException lock) {
                return Result.error(CodeMsg.USERERROR, "用户被锁定");
            } catch (IncorrectCredentialsException exception) {
                return Result.error(CodeMsg.USERERROR, "密码错误");
            }
            return Result.success("登陆成功");
        }
        return Result.error(CodeMsg.USERERROR, "用户名密码不能为空");
    }

可以看到在调用接口的时候,会进行一个输出操作。



版权声明:本文为qq_41822960原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。