1.自定义注解方式
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface RedisLock {
int expire() default 5;
}
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
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.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.RedisLock;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.CheckSumBuilder;
import org.jeecg.common.util.IPUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Aspect
@Configuration
public class RedisLockAspect {
@Value("${spring.profiles.active}") # 本地还是正式 配置文件
private String springProfilesActive;
@Value("${spring.application.name}") #项目名称
private String springApplicationName;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Pointcut("@annotation(org.jeecg.common.aspect.annotation.RedisLock)")
public void point() {
}
@Around("point()")
public Object doaround(ProceedingJoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
RedisLock localLock = method.getAnnotation(RedisLock.class);
try {
String lockUniqueKey = getLockUniqueKey(signature, joinPoint.getArgs());
Integer expire = localLock.expire();
if (expire < 0) {
expire = 5;
}
ArrayList<String> keys = Lists.newArrayList(lockUniqueKey);
String result = stringRedisTemplate.execute(setNxWithExpireTime, keys, expire.toString());
if (!"ok".equalsIgnoreCase(result)) {
log.info("重复提交,请稍后再试");
return Result.error("重复提交,请稍后再试");
}
return joinPoint.proceed();
} catch (Throwable throwable) {
throw new RuntimeException(throwable.getMessage());
}
}
private RedisScript<String> setNxWithExpireTime = new DefaultRedisScript<>(
"return redis.call('set', KEYS[1], 1, 'ex', ARGV[1], 'nx');",
String.class
);
private String getLockUniqueKey(MethodSignature methodSignature, Object[] args) throws NoSuchAlgorithmException {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = servletRequestAttributes.getRequest();
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
String userMsg = sysUser.getUsername();
if (StringUtils.isEmpty(userMsg)) {
userMsg = IPUtils.getIpAddr(request);
}
String hash = "";
List list = new ArrayList();
if (args.length > 0) {
String[] parameterNames = methodSignature.getParameterNames();
for (int i = 0; i < parameterNames.length; i++) {
Object obj = args[i];
list.add(obj);
}
String param = JSONUtil.toJsonStr(list);
hash = CheckSumBuilder.getMD5(param);
}
String key = "lock:" + springApplicationName + ":" + springProfilesActive + ":" + userMsg + ":" + request.getRequestURI();
if (StringUtils.isNotEmpty(key)) {
key = key + ":" + hash;
}
return key;
}
}
使用
@RedisLock
@AutoLog(value = "添加数据")
@ApiOperation(value="添加数据", notes="添加数据")
@PostMapping(value = "/add")
public Result<?> add(@RequestBody A a)throws Exception {
testService.saveTo(a);
return Result.OK("添加成功!");
}