【在线OJ系统】自定义注解实现分布式ID无感自增

实现思路

首先自定义参数注解,然后根据AOP思想,找到该注解作用的切点,也就是mapper层对于mapper层的接口在执行前都会执行该aop操作:获取到对于的方法对象,根据方法对象获取参数列表,根据参数列表判断某个参数上是否加有自定义的注解,如果有则读取注解中的value值,并通过传入对象的引用拿到该对象,此时判断该对象的id值是否位空,如果为空则生成全局唯一id并赋值

代码实现
package com.cloud.cloud_oj_learn.aspects;

import com.cloud.cloud_oj_common.annotations.GenerateId;
import com.cloud.cloud_oj_common.enums.Keys;
import jakarta.annotation.Resource;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: PG
 * Date: 2024-04-16
 * Time: 18:49
 */
@Aspect
@Component
public class GenerateIdAspect {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    // 初始时间戳
    private static final long BEGIN_TIME = 1640995200L;

    // 序列化位数
    private static final int BITE = 32;

    public Long getNext(String tableName) {
        // 1.生成时间戳
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        long timestamp = nowSecond - BEGIN_TIME;

        // 2,生成序列化号
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        long count = stringRedisTemplate.opsForValue().increment(Keys.GENERATE_ID.getKey() + tableName + ":" + date);

        // 3.拼接  返回
        return Long.valueOf(timestamp << BITE | count);
    }


    @Before("execution(* com.cloud.cloud_oj_learn.mapper.*.*(..))")
    public void before(JoinPoint joinPoint) {
        // 获取方法签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 获取方法对象
        Method method = methodSignature.getMethod();
        // 获取方法参数值数组
        Object[] args = joinPoint.getArgs();
        // 获取方法注解
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        for (int i = 0; i < parameterAnnotations.length; i++) {
            for (Annotation annotation : parameterAnnotations[i]) {
                if (annotation instanceof GenerateId) {
                    try {
                        // 获取参数对象
                        Object arg = args[i];
                        // 获取这个对象的类文件
                        Class<?> clazz = arg.getClass();
                        // 获取这个对象的id属性
                        Field idField = clazz.getDeclaredField("id");
                        // 设置字段修改权限
                        idField.setAccessible(true);
                        // 获取注解上的value值
                        String value = ((GenerateId) annotation).value();
                        // 获取该value对应的下一个id
                        Long nextId = getNext(value);
                        // 判断是否为空, 如果为空就赋值 
                        if (idField.get(arg) == null) {
                            idField.set(arg, nextId);
                        }
                    } catch (NoSuchFieldException | IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }

}

图示

相关推荐

  1. springboot redission 定义注解实现分布式

    2024-04-20 23:40:04       40 阅读
  2. Twitter的分布式ID雪花算法snowflake

    2024-04-20 23:40:04       45 阅读
  3. Redis与定义注解实现重复

    2024-04-20 23:40:04       55 阅读
  4. 基于AOP实现定义注解

    2024-04-20 23:40:04       38 阅读
  5. 定义注解+AOP实现日志记录

    2024-04-20 23:40:04       33 阅读
  6. 定义注解实现Excel 导出

    2024-04-20 23:40:04       25 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-20 23:40:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-20 23:40:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-20 23:40:04       82 阅读
  4. Python语言-面向对象

    2024-04-20 23:40:04       91 阅读

热门阅读

  1. 【数学建模】钻井问题

    2024-04-20 23:40:04       32 阅读
  2. WPS二次开发专题:WPS SDK事件回调

    2024-04-20 23:40:04       38 阅读
  3. 安阳旅游地图规划(未完成)

    2024-04-20 23:40:04       26 阅读
  4. React-hooks:useReducer

    2024-04-20 23:40:04       37 阅读
  5. el-table 遇到的问题一

    2024-04-20 23:40:04       30 阅读
  6. 使用JWT、Redis + token实现用户登录的两种方式。

    2024-04-20 23:40:04       31 阅读
  7. Android 13 有线以太网静态ip保存逻辑梳理分析

    2024-04-20 23:40:04       28 阅读
  8. 使用Python实现超参数调优

    2024-04-20 23:40:04       34 阅读
  9. Swift知识点 --- AnyView

    2024-04-20 23:40:04       39 阅读
  10. hyref 开发者推荐项目

    2024-04-20 23:40:04       35 阅读
  11. React Flow浏览器默认事件失效问题解决

    2024-04-20 23:40:04       32 阅读
  12. npm 更改国内镜像的方法

    2024-04-20 23:40:04       38 阅读