一 增加注解
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface ApiIdempotent {
}
二 aop实现切面
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.ec.file100.common.utils.CurrentUserUtil;
import com.ec.file100.employee.annotation.ApiIdempotent;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
@Slf4j
public class IdempotentAspect {
@Around("@annotation(idempotent)")
public Object checkIdempotent(ProceedingJoinPoint joinPoint, ApiIdempotent idempotent) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
String requestURI = request.getRequestURI();
// 方法名 + 请求参数 + 当前用户 标识作为唯一
Object[] args = joinPoint.getArgs();
String jsonParam = JSONObject.toJSONString(args);
String cacheKey = String.format("%s%s%s", requestURI, jsonParam, CurrentUserUtil.getCurrentUserId());
RedissonClient redissonClient = SpringUtil.getBean(RedissonClient.class);
RLock lock = redissonClient.getLock(cacheKey);
if (lock.isLocked()) {
log.info("redis key is lock param: {}", cacheKey);
throw new RuntimeException("请勿重复操作");
}
try {
// 默认超时时间是30秒
lock.lock(30, TimeUnit.SECONDS);
return joinPoint.proceed();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return null;
}
}
三 接口上增加注解
完成