现在application.properties里添加配置文件:
spring.redislocal.host: redis://127.0.0.1 spring.redislocal.port: 6379 spring.redislocal.password: 111111 spring.redislocal.sleeptime: 10000
编写redis工具类:
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.redisson.Redisson; import org.redisson.api.*; import org.redisson.config.Config; import org.redisson.config.SingleServerConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.annotation.Annotation; import java.util.SortedMap; import java.util.TreeMap; public class RedisUtils { private static Logger logger= LoggerFactory.getLogger(RedisUtils.class); private static RedisUtils redisUtils; private static RedissonClient redissonClient; private RedisUtils(){} /** * 提供单例模式 * @return */ public static RedisUtils getInstance(){ if(redisUtils==null) synchronized (RedisUtils.class) { if(redisUtils==null) redisUtils=new RedisUtils(); } return redisUtils; } /** * 使用config创建Redisson * Redisson是用于连接Redis Server的基础类 * @param config * @return */ public static RedissonClient getRedisson(Config config){ RedissonClient redisson= Redisson.create(config); logger.info("成功连接Redis Server"); return redisson; } /** * 使用ip地址和端口创建Redisson * @param ip * @param port * @return */ public static RedissonClient getRedisson(String ip,String port){ Config config=new Config(); config.useSingleServer().setAddress(ip+":"+port); RedissonClient redisson=Redisson.create(config); logger.info("成功连接Redis Server"+"\t"+"连接"+ip+":"+port+"服务器"); return redisson; } /** * 关闭Redisson客户端连接 * @param redisson */ public static void closeRedisson(RedissonClient redisson){ redisson.shutdown(); logger.info("成功关闭Redis Client连接"); } /** * 获取字符串对象 * @param redisson * @param objectName * @return */ public static <T> RBucket<T> getRBucket(RedissonClient redisson, String objectName){ RBucket<T> bucket=redisson.getBucket(objectName); return bucket; } /** * 获取Map对象 * @param redisson * @param objectName * @return */ public static <K,V> RMap<K, V> getRMap(RedissonClient redisson, String objectName){ RMap<K, V> map=redisson.getMap(objectName); return map; } /** * 获取有序集合 * @param redisson * @param objectName * @return */ public static <V> RSortedSet<V> getRSortedSet(RedissonClient redisson, String objectName){ RSortedSet<V> sortedSet=redisson.getSortedSet(objectName); return sortedSet; } /** * 获取集合 * @param redisson * @param objectName * @return */ public static <V> RSet<V> getRSet(RedissonClient redisson, String objectName){ RSet<V> rSet=redisson.getSet(objectName); return rSet; } /** * 获取列表 * @param redisson * @param objectName * @return */ public static <V> RList<V> getRList(RedissonClient redisson,String objectName){ RList<V> rList=redisson.getList(objectName); return rList; } /** * 获取队列 * @param redisson * @param objectName * @return */ public <V> RQueue<V> getRQueue(RedissonClient redisson,String objectName){ RQueue<V> rQueue=redisson.getQueue(objectName); return rQueue; } /** * 获取双端队列 * @param redisson * @param objectName * @return */ public static <V> RDeque<V> getRDeque(RedissonClient redisson,String objectName){ RDeque<V> rDeque=redisson.getDeque(objectName); return rDeque; } /** * 此方法不可用在Redisson 1.2 中 * 在1.2.2版本中可用 * @param redisson * @param objectName * @return */ public static <V> RBlockingQueue<V> getRBlockingQueue(RedissonClient redisson,String objectName){ RBlockingQueue rb=redisson.getBlockingQueue(objectName); return rb; } /** * 获取锁 * @param redisson * @param objectName * @return */ public static RLock getRLock(RedissonClient redisson,String objectName){ RLock rLock=redisson.getLock(objectName); return rLock; } /** * 获取原子数 * @param redisson * @param objectName * @return */ public static RAtomicLong getRAtomicLong(RedissonClient redisson,String objectName){ RAtomicLong rAtomicLong=redisson.getAtomicLong(objectName); return rAtomicLong; } /** * 获取记数锁 * @param redisson * @param objectName * @return */ public static RCountDownLatch getRCountDownLatch(RedissonClient redisson,String objectName){ RCountDownLatch rCountDownLatch=redisson.getCountDownLatch(objectName); return rCountDownLatch; } /** * 获取消息的Topic * @param redisson * @param objectName * @return */ public static <M> RTopic<M> getRTopic(RedissonClient redisson,String objectName){ RTopic<M> rTopic=redisson.getTopic(objectName); return rTopic; } /** * 获取包括方法参数上的key * redis key的拼写规则为 "DistRedisLock+" + lockKey + @DistRedisLockKey<br/> * * @param point * @param lockKey * @return */ public static String getLockKey(ProceedingJoinPoint point, String lockKey) { try { lockKey = "DistRedisLock:" + lockKey; Object[] args = point.getArgs(); if (args != null && args.length > 0) { MethodSignature methodSignature = (MethodSignature)point.getSignature(); Annotation[][] parameterAnnotations = methodSignature.getMethod().getParameterAnnotations(); SortedMap<Integer, String> keys = new TreeMap<>(); for (int i = 0; i < parameterAnnotations.length; i ++) { RedisLockKey redisLockKey = getAnnotation(RedisLockKey.class, parameterAnnotations[i]); if (redisLockKey != null) { Object arg = args[i]; if (arg != null) { keys.put(redisLockKey.order(), arg.toString()); } } } if (keys != null && keys.size() > 0){ for (String key : keys.values()) { lockKey += key; } } } return lockKey; } catch (Exception e) { logger.error("getLockKey error.", e); } return null; } /** * 获取注解类型 * @param annotationClass * @param annotations * @param <T> * @return */ private static <T extends Annotation> T getAnnotation(final Class<T> annotationClass, final Annotation[] annotations) { if (annotations != null && annotations.length > 0) { for (final Annotation annotation : annotations) { if (annotationClass.equals(annotation.annotationType())) { return (T) annotation; } } } return null; } public static RedissonClient createClient(String address , String pass) { if(redissonClient == null) { synchronized (RedisUtils.class) { if(redissonClient == null) { Config config = new Config(); SingleServerConfig singleSerververConfig = config.useSingleServer(); singleSerververConfig.setAddress(address); singleSerververConfig.setPassword(pass); redissonClient = RedisUtils.getInstance().getRedisson(config); } } } return redissonClient; } }
写注解RedisLock:
import java.lang.annotation.*; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface RedisLock { /** * 锁的key * 如果想添加非固定锁,可以在参数上添加@P4jSynKey注解,但是本参数是必写选项<br/> * redis key的拼写规则为 "DistRedisLock+" + lockKey + @RedisLockKey<br/> */ String lockKey(); /** * 持锁时间 * 单位毫秒,默认5秒<br/> */ long keepMills() default 5 * 1000; /** * 没有获取到锁时,等待时间 * @return */ long maxSleepMills() default 20 * 1000; }
写注解RedisLockKey :
import java.lang.annotation.*; @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface RedisLockKey { /** * key的拼接顺序规则 */ int order() default 0; }
写切面:
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.concurrent.TimeUnit; @Component @Aspect public class RedisLockAspect { private static Logger logger= LoggerFactory.getLogger(RedisLockAspect.class); @Value("${spring.redislocal.host}:${spring.redislocal.port}") String address; @Value("${spring.redislocal.password}") String password; @Value("${spring.redislocal.sleeptime}") int sleepTime ; @Around("execution(* com.juphoon.coachtalk.appserver.service..*(..))&& @annotation(RedisLock)") public Object lock(ProceedingJoinPoint point) throws Throwable { RLock lock = null; Boolean status = false; Object object = null; logger.info("into Aspect!"); try { RedisLock redisLock = getDistRedisLockInfo(point); RedisUtils redisUtils = RedisUtils.getInstance(); RedissonClient redissonClient = RedisUtils.createClient(address, password); String lockKey = redisUtils.getLockKey(point, redisLock.lockKey()); lock = redisUtils.getRLock(redissonClient, lockKey); if (lock != null) { status = lock.tryLock(redisLock.maxSleepMills(), redisLock.keepMills(), TimeUnit.MILLISECONDS); if (status) { object = point.proceed(); } } } finally { if (lock != null && status) { lock.unlock(); } } return object; } private RedisLock getDistRedisLockInfo(ProceedingJoinPoint point) { try { MethodSignature methodSignature = (MethodSignature) point.getSignature(); Method method = methodSignature.getMethod(); return method.getAnnotation(RedisLock.class); } catch (Exception e) { logger.info(e.getMessage()); } return null; } }
具体实现的调用:
@RedisLock(lockKey = "lockKey", keepMills = 15000) public void updateXXX(@RedisLockKey(order = 1) Long userId, @RedisLockKey(order = 0) Long advisorId) { }