1、创建注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface RedisLock {
/** 活动key */
String activityKey() default "";
/** 锁存储字符串 */
String valueStr() default "1";
/** 有效期,默认1 */
long timeout() default 1;
/** 有效期单位,默认秒 */
TimeUnit timeUnit() default TimeUnit.SECONDS;
/** 是否在方法执行完成后删除 */
boolean overDel() default true;
}
2、创建切面类
/**
* 使用redis锁注解对方法加锁
* @author lei.yan004
*/
@Component
@Aspect
public class RedisLockAspect {
private static final Logger logger = LoggerFactory.getLogger(RedisLockAspect.class);
@Autowired
private RedisUtil redisUtil;
// 声明公共切入点
@Pointcut("@annotation(com.sinolife.lock.RedisLock)")
private void lockPointCut() {
}
/**
* 方法执行前调用,用于请求加锁
* @param joinPoint
* @return
*/
@Around(value = "lockPointCut()")
public Object lockAround(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
RedisLock annotation = method.getAnnotation(RedisLock.class);
String userId = PlatformContext.currentUser();
if (StringUtil.isDataEmpty(userId)) {
return ResponseResult.fail("登陆超时,请重新登陆");
}
String redisKey = RedisKeyConstant.REDIS_KEY_PUB_LIMIT ;
if(StringUtils.isNotBlank(annotation.activityKey())){
redisKey += annotation.activityKey() + ":" ;
}
redisKey += method.getName() + ":" + userId;
boolean setResult = redisUtil.setIfAbsent(redisKey, annotation.valueStr(), annotation.timeout(), annotation.timeUnit());
if (!setResult) {
return ResponseResult.fail("正在处理中,请勿重复操作");
}
return joinPoint.proceed();
}
/**
* 方法执行完成后调用,用于释放锁
* @param joinPoint
* @return
* @Author lei.yan004
*/
@After("lockPointCut()")
public void lockAfter(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
RedisLock annotation = method.getAnnotation(RedisLock.class);
if (annotation.overDel()) {
String userId = PlatformContext.currentUser();
String redisKey = RedisKeyConstant.REDIS_KEY_PUB_LIMIT;
if (StringUtils.isNotBlank(annotation.activityKey())) {
redisKey += annotation.activityKey() + ":";
}
redisKey += method.getName() + ":" + userId;
redisUtil.delete(redisKey);
}
}
}
3、使用demo
可以通过RedisLock注解的属性,进行一些自定义的配置,例如有效期等
@RedisLock
@RequestMapping("/updateScene")
public ResponseResult<Map<String,Object>> updateScene() {
...
}