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.效果
努力提高自己的技术,不忘初心