1.引入redis
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.yml配置
spring:
redis:
host: localhost
port: 6379
password: 123456
3.自定义注解
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface RedisLock {
int expire() default 5;
}
4. 定义切面类
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.heshu.sz.blockchain.utonhsbs.common.utils.MyMD5Util;
import com.heshu.sz.blockchain.utonhsbs.common.utils.SecurityUtils;
import com.heshu.sz.blockchain.utonhsbs.common.utils.ip.IpUtils;
import com.heshu.sz.blockchain.utonhsbs.framework.interceptor.annotation.RedisLock;
import com.heshu.sz.blockchain.utonhsbs.framework.system.domain.BaseResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.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;
/**
* @author :xx
* @description:
* @date : 2022/7/1 9:41
*/
@Slf4j
@Aspect
@Configuration
public class RedisLockMethodInterceptor {
@Value("${spring.profiles.active}")
private String springProfilesActive;
@Value("${spring.application.name}")
private String springApplicationName;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Pointcut("@annotation(com.heshu.sz.blockchain.utonhsbs.framework.interceptor.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)) {//不存在
return BaseResult.error("不允许重复提交,请稍后再试");
}
return joinPoint.proceed();
} catch (Throwable throwable) {
throw new RuntimeException(throwable.getMessage());
}
}
/**
* lua脚本
*/
private RedisScript<String> setNxWithExpireTime = new DefaultRedisScript<>(
"return redis.call('set', KEYS[1], 1, 'ex', ARGV[1], 'nx');",
String.class
);
/**
* 获取唯一标识key
*
* @param methodSignature
* @param args
* @return
*/
private String getLockUniqueKey(MethodSignature methodSignature, Object[] args) throws NoSuchAlgorithmException {
//请求uri, 获取类名称,方法名称
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = servletRequestAttributes.getRequest();
// HttpServletResponse responese = servletRequestAttributes.getResponse();
//获取用户信息
String userMsg = SecurityUtils.getUsername(); //获取登录用户名称
//1.判断用户是否登录
if (StringUtils.isEmpty(userMsg)) { //未登录用户获取真实ip
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 = JSONObject.toJSONString(list);
hash = MyMD5Util.getMD5(param);
}
//项目名称 + 环境编码 + 获取类名称 + 加密参数
String key = "lock:" + springApplicationName + ":" + springProfilesActive + ":" + userMsg + ":" + request.getRequestURI();
if (StringUtils.isNotEmpty(key)) {
key = key + ":" + hash;
}
return key;
}
5.调用
@RedisLock
public void save(@RequestBody User user) {
}
文章来源:https://blog.csdn.net/qq_33454058/article/details/125516310?spm=1001.2014.3001.5506