spring项目对某条单据进行加锁处理

最近工作中有个对工单单据进行加锁/解锁处理,目的是为了防止多用户对同一条单据处理。以下是完整的前后端代码。

前端JS billLock.js

javascript 复制代码
let orderLock = {
    orderLock:(viewmodel, id, billType)=>{
        var url = '/orderLock/lock?domainKey='+viewmodel.getDomainKey();
        var proxy = cb.rest.DynamicProxy.create({
            ensure: {url: url, method: 'POST'}
        });
        let data = {"id":id, "billType": billType, "ttl": 60*60*12}
        proxy.ensure(data, function (err, result) {
            if (err) {
                cb.utils.alert(err.message, 'error');
            } else {
                cb.utils.alert(result, 'info');
                if(viewmodel.originalViewMeta.cBillNo && viewmodel.originalViewMeta.cBillNo=="02924ed1"){
                    //维修领料页面进入
                    if(result.indexOf('成功') <= 0){
                          viewmodel.biz.action().common.browse(viewmodel)
                          viewmodel.biz.action().common.setMode(viewmodel,"browse");  
                          
                    }
                }else{
                    if(result.indexOf('成功') <= 0){
                        viewmodel.biz.action().common.browse(viewmodel)
                    }
                }
                
            }
        })
    },

    unOrderLock:(viewmodel, id, billType)=>{
        var url = '/orderLock/unLock?domainKey='+viewmodel.getDomainKey();
        var proxy = cb.rest.DynamicProxy.create({
            ensure: {url: url, method: 'POST'}
        });
        var data = {"id":id, "billType": billType}
        proxy.ensure(data, function (err, result) {
            if (err) {
                cb.utils.alert(err.message, 'error');
            } else {
                cb.utils.alert(result, 'info');
            }
        })
    }
}
export default orderLock
  

后端Java 代码

java 复制代码
@RestController
@RequestMapping("/orderLock")
@Slf4j
public class OrderLockController extends BaseController {
    @Autowired
    private GmsRedisUtil gmsRRedisUtil;
    @Autowired
    private UserInfoService userInfoService;

    private String ENGINE_NO = "afterservice";

    /**
     * 加锁
     */
    @PostMapping(value = "/lock")
    public void orderLock(@RequestBody OrderLockDTO orderLockDTO, HttpServletResponse response) {
        try{
            String result;
            UserExtendDto userExtendDto = userInfoService.getUserExtend();
            String nowDate = DateUtil.dateFormat(PartCommonConstants.dateTimeFormatter, LocalDateTime.now());
            String key = ENGINE_NO + "_" + orderLockDTO.getBillType() + "_" + orderLockDTO.getId();
            String message = "锁定人["+userExtendDto.getStaffName()+"]锁定时间["+nowDate+"]";
            Boolean flag = gmsRRedisUtil.tryGetLock(key, message, orderLockDTO.getTtl(), 2);
            if(flag){
                result = "加锁成功!";
            }else{
                String lockValue = gmsRRedisUtil.getObject(key);
                if(lockValue.contains(userExtendDto.getStaffName())){
                    result = "加锁成功!原锁定用户["+userExtendDto.getStaffName()+"]进入单据!";
                }else{
                    result = "加锁失败!单据已被锁定,"+lockValue;
                }
            }
            renderJson(response, ResultMessage.data(result,false));
        }catch(Exception e){
            renderJson(response, ResultMessage.error(e.getMessage()));
            log.error("加锁失败:{}",e);
        }
    }

代码解析(以上代码大致步骤如下:)

1. 前端代码 参数是data,带有id,billtype,字符串ttl,时间变量 4个参数穿入后端。

2.后端接收参数,调用gmsRRedisUtil.tryGetLock,这个方法是项目框架自己封装,原理是实现了redisTemplate.opsForValue().setIfAbsent方法

3.setIfAbsent方法简单介绍如下:

java 复制代码
1.setIfAbsent(K var1, V var2);
如果key不存在则新增,key存在不做任何操作
redisTemplate.opsForValue().setIfAbsent("BBB", "好的");

2.setIfAbsent(K var1, V var2, long var3, TimeUnit var5)
如果key不存在则新增,同时设置过期时间,key存在不做任何操作。
redisTemplate.opsForValue().setIfAbsent("AAA", "好的", 1, TimeUnit.MINUTES);

3.setIfAbsent(K key, V value, Duration timeout)
如果key不存在则新增,同时设置过期时间,key存在不做任何操作。
redisTemplate.opsForValue().setIfAbsent("BBB", "好的", Duration.ofMinutes(1));

4.如果单据第一次进入,key不存在,flag为true,直接返回给前端"加锁成功",前端解析字符串中含有"成功,不设置页面为浏览态,仍为编辑态

复制代码
本次加锁我调用的是第2个方法,这里的第一个参数key可见是单据id加一些特定字符。所以单据id就会被加锁,并设置加锁时间\

5 如果单据在已经加锁的情况下,仍有其他用户编辑此单据,则key重复,gmsRRedisUtil.tryGetLock不做操作。

复制代码
	gmsRRedisUtil.getObject(key)实际是调用redisTemplate.opsForValue().get(key) 方法,
	其中 get(Object var1)  是获取指定的key对应的值。
	第一次加锁的message是用户信息,这里如果是不同用户登录的话,
    if(lockValue.contains(userExtendDto.getStaffName())) 就为false,返回给前端的信息是"加锁失败...",
    前端获取字符串信息中没有加锁成功,会设置页面为浏览态,不能编辑。 到此,加锁完成!
相关推荐
nice_lcj52012 分钟前
Java Lambda 表达式入门:怎么写、怎么用、常用方法有哪些
java·开发语言·后端·面试
码农小河6633 分钟前
基于SSM+JSP+MySQL的在线医疗服务系统的设计与实现
java·开发语言·mysql
IT_陈寒1 小时前
Redis大key删除为什么会导致服务卡顿?我的线上事故复盘
前端·人工智能·后端
系统集成-鹰翔1 小时前
ERP图片改名后仍命中识别缓存:缓存键、十分钟到期与调用计数
javascript·经验分享·后端
用户8356290780511 小时前
使用 Python 在 Excel 中添加和自定义迷你图
后端·python
码事漫谈1 小时前
给AI看一颗❤️,它就开始写递归了
后端
用户8356290780511 小时前
使用 Python 在 Excel 图表中添加趋势线与回归方程
后端·python
你三大爷2 小时前
Netty / Kafka / Redis 保序问题的源码对比与 NIO 框架主流解法
后端·架构
SL_staff2 小时前
从配置失效到逻辑复用:JVS-Logic 如何构建可治理的业务编排中枢
java·spring·产品
特立独行的猫A2 小时前
一份 Markdown 发十个平台:cspub 一稿多投
java·后端·python