使用AOP实现日志系统

120 篇文章 1 订阅
24 篇文章 1 订阅

创建数据库表

首先,通过建表语句,创建日志表,这里是mysql的,如果是oracle记得把varchar换成varchar2

CREATE TABLE `diary` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `user_name` varchar(255) DEFAULT NULL COMMENT '用户姓名',
  `type` varchar(255) DEFAULT NULL COMMENT '操作类型',
  `description` varchar(255) DEFAULT NULL COMMENT '操作描述',
  `model` varchar(255) DEFAULT NULL COMMENT '操作模块',
  `result` varchar(255) DEFAULT NULL COMMENT '操作结果',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时默认当前时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更改时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户操作日志表'

创建实体类

@Data
@NoArgsConstructor
public class OperationLog {
    //自增主键id
    private Integer id;
    //用户姓名
    private String userName;
    //操作类型
    private String type;
    //操作描述
    private String description;
    //操作模块
    private String model;
    //操作结果
    private String result;
}

创建mapper层和service层

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xxx.OperationLogMapper">
  <insert id="insertOperationLog" parameterType="xxx.OperationLog">
      insert into diary_list(user_name,type,description,model,result) values (#{userName},#{type},#{description},#{model},#{result})
  </insert>
</mapper>
@Repository
public interface OperationLogMapper {

    void insertOperationLog(OperationLog log);
}
public interface OperationLogService {

    void insertOperationLog(OperationLog log);
}
@Service
public class OperationLogServiceImpl implements OperationLogService{

    @Autowired
    OperationLogMapper operationLogMapper;

    public void insertOperationLog(OperationLog log) {
        operationLogMapper.insertOperationLog(log);
    }
}

创建自定义注解

@Target(ElementType.METHOD)//注解放置的目标位置即方法级别
@Retention(RetentionPolicy.RUNTIME)//注解在哪个阶段执行
@Documented
public @interface OperationLogAnnotation {

    String operModul() default ""; // 操作模块

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

    String operDesc() default "";  // 操作说明

    String operResult() default "";  // 操作结果
}

创建切面

@Aspect
@Component
@Slf4j
public class OperationLogAspect {

    @Autowired
    OperationLogService operationLogService;

    private Object[] args;
    private String[] argNames;

    /**
     * 设置操作日志切入点   在注解的位置切入代码
     */
    @Pointcut("@annotation(xxx.OperationLogAnnotation)")
    public void operLogPoinCut() {
    }

    //对切点方法进行前置增强,就是在调用切点方法前进行做一些必要的操作,这就成为增强
    @Before("operLogPoinCut()")
    public void getRes(JoinPoint joinPoint) {
        args = joinPoint.getArgs();
        argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
    }


    /**
     * 记录操作日志
     * @param joinPoint 方法的执行点
     * @param result  方法返回值
     * @throws Throwable
     */
    @AfterReturning(returning = "result", value = "operLogPoinCut()")
    public void saveOperLog(JoinPoint joinPoint, Object result) throws Throwable {
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        String token = request.getHeader("token");
        String username = JwtUtil.getUsername(token);
        try {
            OperationLog operationLog = new OperationLog();
            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            //获取切入点所在的方法
            Method method = signature.getMethod();
            //获取操作
            OperationLogAnnotation annotation = method.getAnnotation(OperationLogAnnotation.class);
            if (annotation != null) {
                operationLog.setModel(annotation.operModul());
                String operType = annotation.operType();
                operationLog.setType(operType);
                operationLog.setDescription(annotation.operDesc());
                ResultJson resultJson = (ResultJson) result;
                if ("查询".equals(operType)) {
                    if (resultJson.getCode() == ResultCode.SUCCESS.getCode()) {
                        operationLog.setResult("查询成功");
                    } else {
                        operationLog.setResult("查询失败");
                    }
                } else {
                    String operResult = annotation.operResult();
                    JSONObject jsonObject = new JSONObject();
                    for (String s : operResult.split(",")) {
                        Map<String,Object> map = new HashMap<>();
                        if (s.contains("[")) {
                            String s2 = s.split("\\[")[0];
                            for (int i = 0; i < argNames.length; i++) {
                                String argName = argNames[i];
                                if (s2.equals(argName)) {
                                    map.put(s2,args[i]);
                                }
                            }
                            for (String s1 : s.split("\\[")[1].split("\\]")[0].split(" ")) {
                                Field declaredField = map.get(s2).getClass().getDeclaredField(s1);
                                declaredField.setAccessible(true);
                                Object o = declaredField.get(map.get(s2));
                                jsonObject.put(s1,o);
                            }
                        } else {
                            for (int i = 0; i < argNames.length; i++) {
                                String argName = argNames[i];
                                if (s.equals(argName)) {
                                    jsonObject.put(argName,args[i]);
                                }
                            }
                        }
                    }
                    operationLog.setResult(jsonObject.toString());
                }
                
            }
            //操作用户
            operationLog.setUserName(username);
            //保存日志
            operationLogService.insertOperationLog(operationLog);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

controller层中加入自定义注解

    @OperationLogAnnotation(operModul = "操作模块",operType = "操作类型",operDesc = "操作详情",operResult = "操作结果")

操作结果用逗号分割需要入库的参数,比如

operResult = "id,name,age"

如果入参中有对象的话,可以用[]框住字段,用空格分割

operResult = "id,name,age,demo[id num]"
@Data
@NoArgsConstructor
public class Demo {
    private Integer id;
    private Integer num;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值