<!-- aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
#redis
spring.redisson.address = 127.0.0.1:6379
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CacheLock {
String prefix() default "";
int timeOut() default 5;
TimeUnit timeUnit() default TimeUnit.SECONDS;
}
public class BaseResponse {
public Long TotalCount;
public Long ElapseTime;
public Boolean IsSuccess;
public String Message;
public Object data;
public String token;
public Object tables;
}
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.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Aspect
@Configuration
public class RedisLockAspect {
private static final Logger logger = LoggerFactory.getLogger(RedisLockAspect.class);
private final StringRedisTemplate lockRedisTemplate;
@Autowired
public RedisLockAspect(StringRedisTemplate lockRedisTemplate) {
this.lockRedisTemplate = lockRedisTemplate;
}
@Pointcut("@annotation(com.wjw.kafkaservice.common.CacheLock)")
public void cacheLock(){}
@Around("cacheLock()")
@Async
@ResponseBody
public Object checkLock(ProceedingJoinPoint pjp){
BaseResponse response = new BaseResponse();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String method = pjp.getSignature().getName();
String token = request.getHeader("Token");
if (StringUtils.isEmpty(token)){
response.IsSuccess = false;
response.Message = "Token can't be null ! ";
return response;
}
CacheLock lock = ((MethodSignature) pjp.getSignature()).getMethod().getAnnotation(CacheLock.class);
String lockKey = " Method :" + method + "+ Token (" + token + ")";
try {
final Boolean success = lockRedisTemplate.opsForValue().setIfAbsent(lockKey, "");
if (success) {
Boolean result = lockRedisTemplate.expire(lockKey, lock.timeOut(), lock.timeUnit());
if (result){
logger.info(" redis 加锁成功! key 为:" + lockKey);
return pjp.proceed();
} else {
throw new RuntimeException(" redis 加锁出现异常");
}
} else {
logger.info(" 请勿重复请求!");
response.IsSuccess = false;
response.Message = "请勿重复请求! ";
}
} catch (Throwable throwable) {
response.IsSuccess = false;
response.Message = "系统异常,请重试!";
}
return response;
}
}
@Controller
@RequestMapping("/RedisLock")
public class RedisLockController {
@CacheLock
@PostMapping(value = "test")
@ResponseBody
public BaseResponse test(@RequestBody String message){
BaseResponse response = new BaseResponse();
response.Message = "操作成功";
return response;
}
}
2020-06-24 14:54:18.296 INFO 10748 --- [nio-8081-exec-3] c.w.kafkaservice.common.RedisLockAspect : redis 加锁成功! key 为: Method :test+ Token (itSDXmEICdLO6h+afqBqeOJ7YBzt5hn75py1ywqDVL7Io+8sQ7ygDHlk/b29qHG/Dxdp5hPLjJ83HsyIU5GRwg==)
2020-06-24 14:54:18.654 INFO 10748 --- [nio-8081-exec-4] c.w.kafkaservice.common.RedisLockAspect : 请勿重复请求!
2020-06-24 14:54:19.071 INFO 10748 --- [nio-8081-exec-5] c.w.kafkaservice.common.RedisLockAspect : 请勿重复请求!
2020-06-24 14:54:19.532 INFO 10748 --- [nio-8081-exec-6] c.w.kafkaservice.common.RedisLockAspect : 请勿重复请求!