spring boot redis分布式锁
发表于:2025-01-25 作者:千家信息网编辑
千家信息网最后更新 2025年01月25日,spring boot redis分布式锁参照spring boot redis分布式锁 用注解实现时发现不能满足使用需求于是自己开始摸索解决问题...如下,value 是lock的key,因为业务的
千家信息网最后更新 2025年01月25日spring boot redis分布式锁
spring boot redis分布式锁
参照spring boot redis分布式锁 用注解实现时发现不能满足使用需求
于是自己开始摸索解决问题...
如下,value 是lock的key,因为业务的需要key是 "cancelOrder_123_321" 123是订单ID,321是用户ID
@RedisLock(value = "cancelOrder_#{#order.orderNo}_#{#memberId}")@Transactional(rollbackFor = {RuntimeException.class, Exception.class})public void cancelOrder(Order order, String memberId) { log.info("用户:{},订单号:{} 开始执行取消流程...",order.getOrderNo(),memberId); String orderNo = order.getOrderNo(); Order updateOrder = new Order(); updateOrder.setOrderNo(orderNo); updateOrder.setOrderState(OrderStateEnum.CANCELED.getKey());
长话短说,需要了解详情的朋友看其他大神的博客
为什么我可以这样 cancelOrder_#{#order.orderNo}_#{#memberId} 写?
这里最重要的是什么?
是因为我将这个el表达式字符串,解析成了复合型了.复合型简单点就是List集合,集合里有el表达式和文本,用for顺序执行.
代码如下:
Aspect类
private static final OperationExpressionEvaluator evaluator = new OperationExpressionEvaluator();@Around("lockPoint()")public Object around(ProceedingJoinPoint pjp) throws Throwable{ Method method = ((MethodSignature)pjp.getSignature()).getMethod(); RedisLock redisLock = method.getAnnotation(RedisLock.class); String key = getKey(redisLock.value(),method,pjp.getArgs(),pjp.getTarget()); int retryTimes = redisLock.action().equals(RedisLock.LockFailAction.CONTINUE) ? redisLock.retryTimes() : 0; boolean lock = redisLockImpl.lock(key,redisLock.keepMills(),retryTimes,redisLock.sleepMills()); if(!lock){ log.debug("get lock failed:{}",key); return null; } log.debug("get lock success:{}",key); try{ return pjp.proceed(); }catch (Exception e){ log.error("execute locked method occured an exception",e); } finally { boolean releaseResult = redisLockImpl.releaseLock(key); log.debug("release lock:{}-{}",key,releaseResult ? "success":"failed"); } return null;}private String getKey(String key,Method method,Object [] args,Object target){ if(key.length() <= 0){ return Arrays.toString(args); } return String.valueOf(generateKey(key,method,args,target));}private Object generateKey(String key,Method method,Object [] args,Object target) { EvaluationContext evaluationContext = evaluator.createEvaluationContext(method, args, target, target.getClass(), null); return evaluator.key(key, evaluationContext);}
OperationExpressionEvaluator 类
/** * @author liuhanling * @create 2019-01-14 17:03 * @desc 操作表达式评估器 */public class OperationExpressionEvaluator extends CachedExpressionEvaluator{ private final ParserContext parserContext = new ParserContext() { @Override public boolean isTemplate() { return true; } @Override public String getExpressionPrefix() { return "#{"; } @Override public String getExpressionSuffix() { return "}"; } }; /** * Create an {@link EvaluationContext}. * @param method the method * @param args the method arguments * @param target the target object * @param targetClass the target class * @return the evaluation context */ public EvaluationContext createEvaluationContext(Method method, Object[] args, Object target, Class> targetClass, BeanFactory beanFactory) { //bean context ExpressionRootObject rootObject = new ExpressionRootObject(method, args, target, targetClass); //获取目标方法 Method targetMethod = getTargetMethod(targetClass, method); //评测上下文,主要是处理无用变量 MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(rootObject,targetMethod,args,getParameterNameDiscoverer()); //CacheEvaluationContext evaluationContext = new CacheEvaluationContext(rootObject, targetMethod, args, getParameterNameDiscoverer()); if (beanFactory != null) { evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory)); } return evaluationContext; } public Object key(String keyExpression, EvaluationContext evalContext) { //执行el表达式 复合型 return getParser().parse_Expression(keyExpression,parserContext).getValue(evalContext); } private Method getTargetMethod(Class> targetClass, Method method) { //AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass); //Method targetMethod = this.targetMethodCache.get(methodKey); //if (targetMethod == null) { Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass); if (targetMethod == null) { targetMethod = method; } //this.targetMethodCache.put(methodKey, targetMethod); //} return targetMethod; }}
ExpressionRootObject 类
/** * @author liuhanling * @create 2019-01-14 17:04 * @desc 表达式 rootObject */public class ExpressionRootObject { /** * 方法 */ private final Method method; /** * 参数数组 */ private final Object[] args; /** * 目标对象 */ private final Object target; /** * 目标类 */ private final Class> targetClass; public ExpressionRootObject(Method method, Object[] args, Object target, Class> targetClass) { Assert.notNull(method, "Method is required"); Assert.notNull(targetClass, "targetClass is required"); this.method = method; this.target = target; this.targetClass = targetClass; this.args = args; } public Method getMethod() { return this.method; } public String getMethodName() { return this.method.getName(); } public Object[] getArgs() { return this.args; } public Object getTarget() { return this.target; } public Class> getTargetClass() { return this.targetClass; }}
[1]参考链接(spring boot redis分布式锁) https://my.oschina.net/dengfuwei/blog/1600681
[2]参考链接(el表达式) https://blog.csdn.net/zhoudaxia/article/details/38174169
表达式
分布式
复合型
目标
方法
用户
订单
链接
参考
重要
长话短说
上下
上下文
业务
代码
博客
参数
变量
大神
字符
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
连接数据库出现 数据库登陆
新泰手机app软件开发公司
网络技术考题及答案
妄想山海微信主播都在哪个服务器
Python视频软件开发
宝安区网络技术转移包括什么
华为软件开发标准制定股
网络技术计算机三级时间
西湖论剑 网络安全线上峰会
网络安全能出牛股吗
ios数据库应用高级编程
电大计算机网络技术主要学什么
青岛应用软件开发
战地一如何开服务器
文件服务器迁移到网盘
时评网络安全
linux配置网站服务器
软件开发和互联网有什么不同
如何对高校进行网络安全处罚
投资软件开发公司
股票多屏软件开发
传感器软件开发技术要求
中国软件开发模型
国内有苹果的服务器吗
移动终端软件开发背景
网络安全实习生工作内容
服务器里怎么找到删除文件
服务器 pc 更强
c 增加数据库表列
网络安全将要采购什么