生成订单的api controller:
package com.example.demo.controller;
import com.example.demo.common.aop.NotRepeatSubmit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/commit")
public class CommitController {
@GetMapping("/order")
@NotRepeatSubmit(value = 3000L)
public void order() throws InterruptedException {
log.info("生成订单ok");
Thread.sleep(10000);
}
}
创建注解NotRepeatSubmit :
package com.example.demo.common.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotRepeatSubmit {
long value();
}
实现类:
package com.example.demo.common.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
@Aspect
public class NotRepeatSubmitConfig {
@Autowired
private RedissonClient redissonClient;
@Pointcut("@within(notRepeatSubmit)||@annotation(notRepeatSubmit)")
public void pointcut(NotRepeatSubmit notRepeatSubmit) {
}
@Around(value = "pointcut(notRepeatSubmit)")
public Object around(ProceedingJoinPoint proceedingJoinPoint, NotRepeatSubmit notRepeatSubmit) throws Throwable {
log.info("提交之前---");
Object result = null;
long leaseTime = notRepeatSubmit.value();
log.info("leaseTime:"+leaseTime);
// 设置锁定资源名称,accountUriLock改为userid+uri作为标识,作为测试写死
String accountUriLockKey = "accountUriLock";
RLock accountUriLock = redissonClient.getLock(accountUriLockKey);
boolean tryLock;
//尝试获取分布式锁
tryLock = accountUriLock.tryLock(-1, leaseTime, TimeUnit.MILLISECONDS);
log.info("tryLock:"+tryLock);
if (tryLock) {
try {
log.info("正常提交:");
result = proceedingJoinPoint.proceed();
}catch (Exception e) {
log.info("主程序异常:"+e);
throw new Exception(e);
}
}else {
log.info("重复提交:"+accountUriLockKey);
}
log.info("提交之后---");
return result;
}
}