redisson 一个你值得学习的框架

 

前言

   好久没来博客了,遇到了一些好东西分享给大家,不喜勿喷!


 

一、redisson是什么?能干什么?

redisson是基于redis 的一种开源框架,该框架是为了方便我们使用redis而再度封装的一个框架。也不多做介绍了。

官方文档连接:https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95

在我们项目中,它来干什么呢?我想到是结合aop和自定义注解实现redis的分布式锁控制,使我们的加锁解锁得以统一控制。接下来期待下吧!上代码。

二、使用步骤

1.引入库

pom如下:


   org.redisson
   redisson
   3.11.6

2.实现方式

首先需要我们在容器中注入redisClient。我们的redisConfig配置类如下

/**
 * 启动程序的时候来初始化这个类
   @PropertySource 加载指定配置文件
 */

@Configuration
@PropertySource("classpath:config/redis.properties")
public class RedisConfig {
// #Matser的ip地址  
    @Value("${redis.hostName}")
   private String MASTER_HOST;
   //#端口号  
    @Value("${redis.port}")
   private Integer PORT;
   // 密码  
    @Value("${redis.password}")
   private String PASSWORD;
   
   //最大空闲数  
    @Value("${redis.maxIdle}")
    private Integer maxIdle;

 
    public RedisConfig() {
   System.out.println("初始化redisTemplate。。。。。。。。。。。");
   }

    @Bean(name = "redisClient")
    public RedissonClient redisClient() {
        Config config = new Config();
        config.useSingleServer()
                //.setPassword(PASSWORD)
                .setTimeout(1000000)
                //这里注意address 必须redis:// 或者rediss:// 开头
                // 不然会报错
                .setAddress("redis://127.0.0.1:6379");
               // .setConnectionMinimumIdleSize(maxWaitMillis)
        ;
        return  Redisson.create(config);
    } 
  
    }

 

 

接下来使我们的自定义注解 :



/**
 * 自定义分布式锁注解 配合 aop + Redisson 实现分布式锁
 */
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisDistlock {
    /**
     * 锁的名称。 如果lockName可以确定,直接设置该属性。
     */
    String lockName() default "";

    /**
     * 
     *     获取注解的方法参数列表的某个参数对象的某个属性值来作为lockName。因为有时候lockName是不固定的。
     *     当param不为空时,可以通过argNum参数来设置具体是参数列表的第几个参数,不设置则默认取第一个。
     * 
*/ String param() default ""; /** * 获得锁名时拼接前后缀用到的分隔符 * * @return */ String separator() default ":"; /** * 锁超时时间。 超时时间过后,锁自动释放 默认8秒。 建议: 尽量缩简需要加锁的逻辑。 */ long leaseTime() default 8L; /** * 时间单位。默认为秒。 */ TimeUnit timeUnit() default TimeUnit.SECONDS; }

 

aop实现如下:



/**
 * redis分布式锁 切面处理
 * aop 切面处理 redisson分布式加锁操作
 *
 * @author chenhengtong
 */
@Aspect
@Component("admincenterRedisDistlockAspect")
@Log4j
@Order(-1)
public class RedisDistlockAspect {

    /**
     * 分布式锁 key
     */
    public static final String REDIS_DISTLOCK_PREFIX = "distlock:%s";

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 切入点为加了 @RedissonLock 注解
     */
    @Pointcut("@annotation(com.ssq.www.springboot.aspect.RedisDistlock)")
    public void RedissonLockAspect() {

    }

    @Around("RedissonLockAspect()")
    public Object lockAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Method method = null;
        RedisDistlock redisDistlock;
        RLock rLock = null;
        long start = 0L;
        try {
            method = getPointMethod(proceedingJoinPoint);
            // 获取方法上的分布式锁注解
            redisDistlock = method.getAnnotation(RedisDistlock.class);
            long expireTime = redisDistlock.leaseTime();
            String teamSequence = getTeamSequence(proceedingJoinPoint);
            String distlockKey = String.format(REDIS_DISTLOCK_PREFIX, teamSequence);
            System.out.println("加锁 key  distlockKey = " + distlockKey);
            start = System.currentTimeMillis();
            //获取锁
            rLock = redissonClient.getLock(distlockKey);
            //设置超时
            rLock.lock(expireTime, redisDistlock.timeUnit());
            return proceedingJoinPoint.proceed();
        } finally {
            try {
                if (rLock != null && rLock.isLocked()) {
                    rLock.unlock();
                }
                log.info("锁释放完成");
            } catch (Exception e) {
                log.error("redis 分布式锁释放异常!", e);
            }
            String methodName = method.getName();
            log.info(">> " + methodName + " cost " + (System.currentTimeMillis() - start) + " ms");
        }
    }

    /**
     * 获取切入点的方法
     *
     * @param joinPoint
     * @return
     */
    private Method getPointMethod(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        return methodSignature.getMethod();
    }


    /**
     * 通过方法参数获取车队序列号的值
     *
     * @param joinPoint
     * @return
     */
    private String getTeamSequence(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        // 参数名
        String[] parameterNames = methodSignature.getParameterNames();
        // 参数值对象
        Object[] parameterValues = joinPoint.getArgs();

        Method method = getPointMethod(joinPoint);
        RedisDistlock rlock = method.getAnnotation(RedisDistlock.class);
        String teamSequence = null;

        String lockName = rlock.lockName();
        String param = rlock.param();
        String separator = rlock.separator();

        if (StringUtils.isEmpty(lockName)) {
            lockName = method.getName();
        }


        if (!StringUtils.isEmpty(parameterValues)) {

            for (int i = 0; i < parameterNames.length; i++) {
                //未设置pram考虑 取第一个参数值
                if (StringUtils.isEmpty(param)) {
                    param = parameterValues[i].toString();
                    teamSequence = lockName + separator + param;
                    break;
                } else if (param.equalsIgnoreCase(parameterNames[i])) {
                    teamSequence = lockName + separator + parameterValues[i].toString();
                    break;
                } else {
                    teamSequence = reflectTeamSequence(parameterValues[i], param);
                    if (StringUtils.isEmpty(teamSequence)) {
                        continue;
                    }
                    teamSequence = lockName + separator + teamSequence;
                    break;
                }
            }
            if (!StringUtils.isEmpty(teamSequence)) {
                return teamSequence;
            }
        }
        throw new RuntimeException("锁ID为空");
    }

    /**
     * 反射获取 注解制定的参数 
     *
     * @param param 方法上的参数对象
     * @return
     */
    private String reflectTeamSequence(Object param, String paramName) {
        if (param == null) {
            return "";
        }
        // 1. 获取其从父类继承下来的所有字段( Object.class 排除)
        List fieldList = new ArrayList<>();
        Class clazz = param.getClass();
        while (clazz != null && !clazz.equals(Object.class)) {
            fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass();
        }
        // 2. 返回参数的值
        for (Field field : fieldList) {
            field.setAccessible(true);
            // 字段名称
            String fieldName = field.getName();
            Object fieldValue;
            if (paramName.equalsIgnoreCase(fieldName)) {
                try {
                    fieldValue = field.get(param);
                    if (!StringUtils.isEmpty(fieldValue)) {
                        return fieldValue.toString();
                    }
                } catch (IllegalAccessException e) {
                    // 已经设置了accessible ...
                    log.error("join pointer reflect get paramName error!", e);
                }
                break;
            }
        }
        return "";
    }

}

 


总结

以上就是今天要讲的内容,本文仅仅简单介绍了redisson的一种使用,希望对大家有用。

你可能感兴趣的:(工具类,java,spring,boot,redis)