spring项目对某条单据进行加锁处理的方法
作者:大黄烽
最近工作中有个对工单单据进行加锁/解锁处理,目的是为了防止多用户对同一条单据处理。以下是完整的前后端代码。
前端JS billLock.js
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 代码
@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方法简单介绍如下:
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,返回给前端的信息是“加锁失败...”,
前端获取字符串信息中没有加锁成功,会设置页面为浏览态,不能编辑。 到此,加锁完成!
总结
到此这篇关于spring项目对某条单据进行加锁处理的文章就介绍到这了,更多相关spring某条单据加锁处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!