前言一、设计说明二、代码示例
1.自定义注解2.统一的请求入参对象3.AOP处理4.请求示例
前言分布式锁应该是日常工作中常见的一种需求,本文将演示如何通过注解的方式,快速实现分布式锁的功能。
一、设计说明分布式锁的简单实现可以借助Redis来完成,加锁时直接利用SET_IF_ABSENT来控制,如果SET成功则表示加锁成功,如果已存在表示业务流程还在锁定中,则直接返回,最后流程处理完之后,将KEY值删除即可。
二、代码示例 1.自定义注解import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisDistributedLock {
String name() default "";
String field() default "";
long expiration();
Class type();
}
2.统一的请求入参对象
可根据自身公司实际情况修改
@Data public class RequestData3.AOP处理{ private Header header; private T body; } @Data public class Header { private String token; } @Data public class Order { String orderId; }
import com.springboot.micrometer.annotation.RedisDistributedLock;
import com.springboot.micrometer.entity.RequestData;
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.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Map;
@Aspect
@Component
public class RedisDistributedLockAspect {
@Resource
private RedisTemplate redisTemplate;
@Pointcut("@annotation(com.springboot.micrometer.annotation.RedisDistributedLock)")
public void redisDistributedLock() {
}
@Around("redisDistributedLock()")
public Object methodAround(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
RedisDistributedLock redisDistributedLock = method.getAnnotation(RedisDistributedLock.class);
String field = redisDistributedLock.field();
String name = redisDistributedLock.name();
long expiration = redisDistributedLock.expiration();
Class clazzType = redisDistributedLock.type();
String fieldValue;
Object object = clazzType.newInstance();
Map paramValue = AopUtils.getParamValue(joinPoint);
if (object instanceof String) {
fieldValue = (String) paramValue.get(name);
} else if (object instanceof RequestData) {
RequestData requestData = (RequestData) paramValue.get(name);
fieldValue = String.valueOf(AopUtils.getFieldValue(requestData.getBody(), field));
} else {
throw new IllegalArgumentException("不支持的参数类型");
}
if (lock(fieldValue, fieldValue, expiration)) {
try {
return joinPoint.proceed();
} finally {
unlock(fieldValue);
}
}
return "重复请求";
}
public void unlock(String key) {
redisTemplate.delete(key);
}
public boolean lock(@NonNull String key, String value, @NonNull long timeout) {
return redisTemplate.execute((RedisCallback) connection -> connection.set(key.getBytes(), value.getBytes(), Expiration.seconds(timeout), RedisStringCommands.SetOption.SET_IF_ABSENT));
}
}
4.请求示例
import com.springboot.micrometer.annotation.RedisDistributedLock;
import com.springboot.micrometer.entity.Order;
import com.springboot.micrometer.entity.RequestData;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/distribute")
public class DistributedLockController {
@RedisDistributedLock(field = "orderId", name = "order", expiration = 10, type = RequestData.class)
@RequestMapping("/query")
public String query(@RequestBody RequestData order) {
return "success";
}
}



