【在线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);
                    }
                }
            }
        }
    }

}

图示

相关推荐
CodeCraft Studio15 分钟前
国产化Word处理控件Spire.Doc教程:通过C# 删除 Word 文档中的超链接
开发语言·c#·word
martian66527 分钟前
麒麟系统下Tomcat部署Java Web程序(WAR包)及全链路问题排查指南
开发语言·tomcat·系统安全
ai.Neo28 分钟前
牛客网NC22012:判断闰年问题详解
开发语言·c++·算法
web1508541593532 分钟前
使用Python开发经典俄罗斯方块游戏
python·游戏·pygame
好吃的肘子34 分钟前
ElasticSearch进阶
大数据·开发语言·分布式·算法·elasticsearch·kafka·jenkins
缘友一世36 分钟前
PyTorch LSTM练习案例:股票成交量趋势预测
pytorch·python·lstm
NaclarbCSDN40 分钟前
Java集合框架
java·开发语言·前端
xiaohanbao091 小时前
day26 Python 自定义函数
开发语言·python·学习·机器学习·信息可视化·numpy
jie188945758661 小时前
c++,windows,多线程编程详细介绍
开发语言·c++
破晓的历程1 小时前
Qt file文件操作详解
开发语言·qt