SpringBoot 自定义注解,轻松实现 Redis 分布式锁
1.自定义注解类
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ReqFastLimit {
//redis key
String key() default "";
//过期时间 单位秒
long expire() default 60L;
// 前缀
String prefix() default "";
}
2.定义切面
@Aspect
@Component
@Slf4j
@SuppressWarnings("ALL")
public class ReqFastHandler {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private HttpServletRequest request;
@Around(("@annotation(reqFastLimit)"))
public Object around(ProceedingJoinPoint joinPoint, ReqFastLimit reqFastLimit) throws Throwable {
String requestURI = request.getRequestURI();
String keySpel = reqFastLimit.key();
long expire = reqFastLimit.expire();
String prefix = reqFastLimit.prefix();
Object[] args = joinPoint.getArgs();
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
//获取被拦截方法参数名列表(使用Spring支持类库)
LocalVariableTableParameterNameDiscoverer localVariableTable = new LocalVariableTableParameterNameDiscoverer();
String[] paraNameArr = localVariableTable.getParameterNames(method);
//使用SPEL进行key的解析
ExpressionParser parser = new SpelExpressionParser();
//SPEL上下文
StandardEvaluationContext context = new StandardEvaluationContext();
//把方法参数放入SPEL上下文中
for (int i = 0; i < paraNameArr.length; i++) {
context.setVariable(paraNameArr[i], args[i]);
}
String key = null;
// 使用变量方式传入业务动态数据
if (keySpel.matches("^#.*.$")) {
String[] split = keySpel.split(",");
for (String s : split) {
if (key == null) {
key = parser.parseExpression(s).getValue(context, String.class);
} else {
key = key + ":" + parser.parseExpression(s).getValue(context, String.class);
}
}
}
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(prefix + key, key, expire, TimeUnit.SECONDS);
if (!result) {
log.info("key={}", prefix + key);
throw new Exception("您手速真快,慢点吧!");
}
return joinPoint.proceed();
} catch (CustomException e) {
throw e;
} finally {
//代码逻辑执行完释放锁
redisTemplate.delete(prefix + key);
}
}
3.注解使用
@ReqFastLimit(key = "#test.orderNo,#test.channo", expire = 3, prefix = "test")
public ResultVo test(@RequestBody @Valid Test test) {
return testService.test(test);
}
4.效果

努力提高自己的技术,不忘初心

浙公网安备 33010602011771号