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);
? ? ? ? }
? ? ? ? //項目名稱 + 環(huán)境編碼 + 獲取類名稱 + 加密參數(shù)
? ? ? ? String key = "lock:" + springApplicationName + ":" + springProfilesActive + ":" + userMsg + ":" + request.getRequestURI();
? ? ? ? if (StringUtils.isNotEmpty(key)) {
? ? ? ? ? ? key = key + ":" + hash;
? ? ? ? }
? ? ? ? return key;
? ? }
5.調(diào)用
@RedisLock?
?public void save(@RequestBody User user) {
? ? }
文章來源:https://blog.csdn.net/qq_33454058/article/details/125516310?spm=1001.2014.3001.5506