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;@Autowiredprivate 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("添加成功!");}