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

}

图示

相关推荐
油丶酸萝卜别吃3 小时前
utils.js 说明文档
开发语言·javascript·ecmascript
leisoo80976 小时前
100GBA股股票数据怎么存ClickHouseRedisMySQLJSON完整对比
大数据·linux·服务器·开发语言·python
WangYan20226 小时前
基于XGBoost与AI的生态—地学多源数据建模:植被与土地利用识别、土壤碳氮空间预测、生物多样性驱动机制、土壤微生物功能预测、生态退化与风险识别
python·机器学习·xgboost
不会代码的小猴7 小时前
21. 泛型编程上
开发语言·c++·笔记·算法
一只旭宝8 小时前
细讲C加加【9】C++ std::function与std::bind详解|仿函数、绑定器、类成员绑定、占位符、成员偏移指针
开发语言·c++·算法
金銀銅鐵9 小时前
[Python] 借助 turtle 逐字展示唐诗《金缕衣》
python
coder!mq10 小时前
说几个常见的语法糖?
java·开发语言·算法
gugucoding10 小时前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言
Lhan.zzZ10 小时前
在 Visual Studio 2022 中打造可扩展的动态链接库模块:从零搭建到原理解析
开发语言·c++·visual studio
心平气和量大福大10 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言