网络互斥实现方案原创
29次浏览
未经作者许可,禁止转载编辑于2024年07月17日 18:18:35
public class MutexControlUtil {
public static final MutexControlUtil me = new MutexControlUtil();
private static final Log logger = LogFactory.getLog(MutexControlUtil.class);
/**
* 释放锁
* @param entityKey 单据标识
* @param operKey 操作
* @param pkids 单据ID
* @return
*/
public Boolean release(String entityKey, String operKey, List<Object> pkids){
for(Object pkid : pkids){
boolean val = MutexHelper.release(entityKey, operKey, pkid.toString());
System.out.println("解锁:" + val);
}
return true;
}
/**
* 批量释放锁
* @param entityKey 单据标识
* @param operKey 操作
* @param pkids 单据ID
* @return
*/
public boolean batchRelease(String entityKey, String operKey, List<Object> pkids){
try (DataMutex dataMutex = DataMutex.create()) {
String groupId = "default_netctrl";
List<Map<String, Object>> mutexRequireList = new ArrayList<>();
for(Object id : pkids){
Map<String, Object> requireParam = new HashMap<>();
requireParam.put(DataMutex.PARAMNAME_DATAOBJID, String.valueOf(id));
requireParam.put(DataMutex.PARAMNAME_GROUPID, groupId);
requireParam.put(DataMutex.PARAMNAME_ENTITYKEY, entityKey);
requireParam.put(DataMutex.PARAMNAME_OPERATIONKEY, operKey);
mutexRequireList.add(requireParam);
}
Map<String, Boolean> mutexResult = dataMutex.batchRelease(mutexRequireList);
// 分析网控申请结果
for (Map.Entry<String, Boolean> mutexItem : mutexResult.entrySet()) {
String objId = mutexItem.getKey();
Boolean ret = mutexItem.getValue();
if (ret) {
//申请互斥成功的
System.out.println("1111111");
} else {
Map lockInfo = dataMutex.getLockInfo(objId, groupId, entityKey);
if (lockInfo != null) {
//提示锁信息
logger.info("释放锁失败,单据ID:",objId);
}
}
}
} catch (Exception e) {
logger.error("释放锁失败,原因如下:", e.getMessage(), e);
}
return true;
}
/**
* 批量互斥锁校验
* @param entityId 单据标识
* @param pkids 单据ID集合
* @param opKey 操作
* @param errMsg 错误信息
* @return
*/
public Boolean batchRequire(String entityId, List<Object> pkids, String opKey, StringBuilder errMsg){
DynamicObjectCollection cols = QueryServiceHelper.query(entityId, "id,billno",
new QFilter[]{new QFilter("id", "in", pkids)});
Map<String,String> colMaps = Maps.newHashMap();
for(DynamicObject dyn : cols){
colMaps.put(dyn.getString("id"),dyn.getString("billno"));
}
try (DataMutex dataMutex = DataMutex.create()) {
//申请网络互斥锁
//如果需要和标准操作(如保存、提交、审核...)互斥,则可使用default_netctrl(默认分组),不需要和标准操作互斥则需要用自定义的groupId
String groupId = "default_netctrl";
String entityKey = entityId;
List<Map<String, Object>> mutexRequireList = new ArrayList<>();
for(Object id : pkids){
Map<String, Object> requireParam = new HashMap<>();
requireParam.put(DataMutex.PARAMNAME_DATAOBJID, String.valueOf(id));
requireParam.put(DataMutex.PARAMNAME_DATA_OBJ_NUMBER, colMaps.get(id.toString()));
requireParam.put(DataMutex.PARAMNAME_GROUPID, groupId);
requireParam.put(DataMutex.PARAMNAME_ENTITYKEY, entityKey);
requireParam.put(DataMutex.PARAMNAME_OPERATIONKEY, opKey);
requireParam.put(DataMutex.PARAMNAME_ISSTRICT, true);
//建议设置自定义标识,用于后续区分标准操作和自定义申请的网控
requireParam.put(DataMutex.PARAMNAME_DATA_CALL_SOURCE, "missionWare");
mutexRequireList.add(requireParam);
}
Map<String, Boolean> mutexResult = dataMutex.batchrequire(mutexRequireList);
// 分析网控申请结果
for (Map.Entry<String, Boolean> mutexItem : mutexResult.entrySet()) {
String objId = mutexItem.getKey();
Boolean ret = mutexItem.getValue();
if (ret) {
//申请互斥成功的
Map<String, String> lockInfo = dataMutex.getLockInfo(objId, groupId, entityKey);
if (lockInfo != null) {
//申请锁失败,提示已经存在的锁信息
String userName = "XXX";
if(StringUtils.isNotBlank(lockInfo.get("userid"))){
MainEntityType dt = EntityMetadataCache.getDataEntityType("bos_user");
long userId = Long.parseLong(lockInfo.get("userid"));
Map<Object, DynamicObject> cacheUserObjs = BusinessDataReader.loadFromCache(new Object[]{userId}, dt);
DynamicObject userObj = (DynamicObject)cacheUserObjs.get(userId);
if (userObj != null) {
userName = userObj.getString("name");
}
}
errMsg.append(String.format("当前单据{%s},已被{%s}打开!", colMaps.get(objId),userName));
}else {
errMsg.append(String.format("当前单据{%s},已被打开,请联系管理员!", colMaps.get(objId)));
}
}
}
} catch (Exception e) {
result = false;
errMsg.append("当前程序异常,请联系管理员");
logger.error("互斥锁失败,原因如下:", e.getMessage(), e);
}
}
/**
* 锁定 (局限:当前人已打开的数据,不会校验)
* @param entityId 单据标识
* @param pkids 单据ID集合
* @param opKey 操作
* @param errMsg 错误消息
* @return
*/
public Boolean require(String entityId, List<Object> pkids, String opKey, StringBuilder errMsg){
StringBuilder msg = new StringBuilder();
Boolean result = true;
List<Object> successList = Lists.newArrayList();
for(Object pkid : pkids){
if(!MutexHelper.require(entityId, pkid, opKey, msg)){
result = false; //失败
errMsg.append(msg.toString());
}else {
successList.add(pkid);
}
}
if(!result){
//释放锁定成功的数据(因:会产生锁定数据)
MutexControlUtil.me.release(entityId,opKey,successList);
}
return result;
}
}
public static final MutexControlUtil me = new MutexControlUtil();
private static final Log logger = LogFactory.getLog(MutexControlUtil.class);
/**
* 释放锁
* @param entityKey 单据标识
* @param operKey 操作
* @param pkids 单据ID
* @return
*/
public Boolean release(String entityKey, String operKey, List<Object> pkids){
for(Object pkid : pkids){
boolean val = MutexHelper.release(entityKey, operKey, pkid.toString());
System.out.println("解锁:" + val);
}
return true;
}
/**
* 批量释放锁
* @param entityKey 单据标识
* @param operKey 操作
* @param pkids 单据ID
* @return
*/
public boolean batchRelease(String entityKey, String operKey, List<Object> pkids){
try (DataMutex dataMutex = DataMutex.create()) {
String groupId = "default_netctrl";
List<Map<String, Object>> mutexRequireList = new ArrayList<>();
for(Object id : pkids){
Map<String, Object> requireParam = new HashMap<>();
requireParam.put(DataMutex.PARAMNAME_DATAOBJID, String.valueOf(id));
requireParam.put(DataMutex.PARAMNAME_GROUPID, groupId);
requireParam.put(DataMutex.PARAMNAME_ENTITYKEY, entityKey);
requireParam.put(DataMutex.PARAMNAME_OPERATIONKEY, operKey);
mutexRequireList.add(requireParam);
}
Map<String, Boolean> mutexResult = dataMutex.batchRelease(mutexRequireList);
// 分析网控申请结果
for (Map.Entry<String, Boolean> mutexItem : mutexResult.entrySet()) {
String objId = mutexItem.getKey();
Boolean ret = mutexItem.getValue();
if (ret) {
//申请互斥成功的
System.out.println("1111111");
} else {
Map lockInfo = dataMutex.getLockInfo(objId, groupId, entityKey);
if (lockInfo != null) {
//提示锁信息
logger.info("释放锁失败,单据ID:",objId);
}
}
}
} catch (Exception e) {
logger.error("释放锁失败,原因如下:", e.getMessage(), e);
}
return true;
}
/**
* 批量互斥锁校验
* @param entityId 单据标识
* @param pkids 单据ID集合
* @param opKey 操作
* @param errMsg 错误信息
* @return
*/
public Boolean batchRequire(String entityId, List<Object> pkids, String opKey, StringBuilder errMsg){
DynamicObjectCollection cols = QueryServiceHelper.query(entityId, "id,billno",
new QFilter[]{new QFilter("id", "in", pkids)});
Map<String,String> colMaps = Maps.newHashMap();
for(DynamicObject dyn : cols){
colMaps.put(dyn.getString("id"),dyn.getString("billno"));
}
Boolean result = true;
List<Object> successList = Lists.newArrayList();
try (DataMutex dataMutex = DataMutex.create()) {
//申请网络互斥锁
//如果需要和标准操作(如保存、提交、审核...)互斥,则可使用default_netctrl(默认分组),不需要和标准操作互斥则需要用自定义的groupId
String groupId = "default_netctrl";
String entityKey = entityId;
List<Map<String, Object>> mutexRequireList = new ArrayList<>();
for(Object id : pkids){
Map<String, Object> requireParam = new HashMap<>();
requireParam.put(DataMutex.PARAMNAME_DATAOBJID, String.valueOf(id));
requireParam.put(DataMutex.PARAMNAME_DATA_OBJ_NUMBER, colMaps.get(id.toString()));
requireParam.put(DataMutex.PARAMNAME_GROUPID, groupId);
requireParam.put(DataMutex.PARAMNAME_ENTITYKEY, entityKey);
requireParam.put(DataMutex.PARAMNAME_OPERATIONKEY, opKey);
requireParam.put(DataMutex.PARAMNAME_ISSTRICT, true);
//建议设置自定义标识,用于后续区分标准操作和自定义申请的网控
requireParam.put(DataMutex.PARAMNAME_DATA_CALL_SOURCE, "missionWare");
mutexRequireList.add(requireParam);
}
Map<String, Boolean> mutexResult = dataMutex.batchrequire(mutexRequireList);
// 分析网控申请结果
for (Map.Entry<String, Boolean> mutexItem : mutexResult.entrySet()) {
String objId = mutexItem.getKey();
Boolean ret = mutexItem.getValue();
if (ret) {
//申请互斥成功的
System.out.println("111111");
successList.add(objId);
} else {
Map<String, String> lockInfo = dataMutex.getLockInfo(objId, groupId, entityKey);
if (lockInfo != null) {
//申请锁失败,提示已经存在的锁信息
String userName = "XXX";
if(StringUtils.isNotBlank(lockInfo.get("userid"))){
MainEntityType dt = EntityMetadataCache.getDataEntityType("bos_user");
long userId = Long.parseLong(lockInfo.get("userid"));
Map<Object, DynamicObject> cacheUserObjs = BusinessDataReader.loadFromCache(new Object[]{userId}, dt);
DynamicObject userObj = (DynamicObject)cacheUserObjs.get(userId);
if (userObj != null) {
userName = userObj.getString("name");
}
}
errMsg.append(String.format("当前单据{%s},已被{%s}打开!", colMaps.get(objId),userName));
}else {
errMsg.append(String.format("当前单据{%s},已被打开,请联系管理员!", colMaps.get(objId)));
}
}
}
} catch (Exception e) {
result = false;
errMsg.append("当前程序异常,请联系管理员");
logger.error("互斥锁失败,原因如下:", e.getMessage(), e);
}
if(!result && successList.size() > 0){
MutexControlUtil.me.batchRelease(entityId,opKey,successList);
}
return result;MutexControlUtil.me.batchRelease(entityId,opKey,successList);
}
}
/**
* 锁定 (局限:当前人已打开的数据,不会校验)
* @param entityId 单据标识
* @param pkids 单据ID集合
* @param opKey 操作
* @param errMsg 错误消息
* @return
*/
public Boolean require(String entityId, List<Object> pkids, String opKey, StringBuilder errMsg){
StringBuilder msg = new StringBuilder();
Boolean result = true;
List<Object> successList = Lists.newArrayList();
for(Object pkid : pkids){
if(!MutexHelper.require(entityId, pkid, opKey, msg)){
result = false; //失败
errMsg.append(msg.toString());
}else {
successList.add(pkid);
}
}
if(!result){
//释放锁定成功的数据(因:会产生锁定数据)
MutexControlUtil.me.release(entityId,opKey,successList);
}
return result;
}
}
推荐阅读