Index: ssts-datasync-default-impl/src/main/java/com/forgon/disinfectsystem/mq/dao/gzsdbrmyy/MQHelper.java =================================================================== diff -u --- ssts-datasync-default-impl/src/main/java/com/forgon/disinfectsystem/mq/dao/gzsdbrmyy/MQHelper.java (revision 0) +++ ssts-datasync-default-impl/src/main/java/com/forgon/disinfectsystem/mq/dao/gzsdbrmyy/MQHelper.java (revision 31655) @@ -0,0 +1,384 @@ +package com.forgon.disinfectsystem.mq.dao.gzsdbrmyy; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; + +import net.sf.json.JSON; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; + +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.io.SAXReader; + +import com.forgon.disinfectsystem.common.CssdUtils; +import com.forgon.disinfectsystem.datasynchronization.model.OrgUnitVo; +import com.forgon.disinfectsystem.datasynchronization.model.UserVo; +import com.ibm.mq.MQException; +import com.ibm.mq.MQGetMessageOptions; +import com.ibm.mq.MQMessage; +import com.ibm.mq.MQQueue; +import com.ibm.mq.MQQueueManager; +import com.ibm.mq.constants.MQConstants; + +/** + * MQ队列帮助类 + * @author zhouPeiMian + * @since 2021-07-07 + * + */ +public class MQHelper { + + private static Logger logger = Logger.getLogger(MQHelper.class); + @SuppressWarnings("rawtypes") + private static Hashtable env = new Hashtable(); + + // 队列管理器名 + private static String managerName; + // 队列管理器引用 + private static MQQueueManager queueManager; + // 队列名 + private static String queueName; + // 队列引用 + private static MQQueue queue; + + /** + * 科室队列名称 + */ + public static final String DEPARTMQUEUE = "OUT.S008.MS025.LQ"; + + /** + * 人员队列名称 + */ + public static final String USERMQUEUE = "OUT.S008.MS024.LQ"; + + /** + * 应用启动时初始化队列管理器连队列管理器 由于连接队列管理器如同连接数据一样,建立时需要资源较多, + * 连接时间较长,因此不要每次创建关闭,建议应用程序保持连接; 多个队列管理器连接, 应用关闭时注意关闭连接,释放资源! + * 长连接调用initEnvironment方法后,初始化成功后,不要调用destroyEnvironment方法释放连接,就为长连接; + * 短连接则为相反,使用完后调用destroyEnvironment方法; + * 长/短连接什么场景使用?业务场景交互较多,需要时时连接平台收消息时,请使用长连接。反之场景交互少的厂商则选用短连接较为合适。 + * 使用短连接请注意一定要先关闭队列,再关闭队列管理器;这样就能够完全释放连接,以供其他系统使用 + * + * @throws Exception + */ + + private static void initEnvironment(String host, String channal, + String qmn, String quename) throws Exception { + // 服务器地id、名称 + env.put(MQConstants.HOST_NAME_PROPERTY, host); + // 连接通道 + env.put(MQConstants.CHANNEL_PROPERTY, channal); + // 服务器MQ服务使用的编1381代表GBK,1208代表UTF(Coded Character Set Identifier:CCSID) + env.put(MQConstants.CCSID_PROPERTY, 1208); + // 端口号 + env.put(MQConstants.PORT_PROPERTY, 6000); + // 传输类型 + env.put(MQConstants.TRANSPORT_PROPERTY, MQConstants.TRANSPORT_MQSERIES); + // 设置目标队列管理器 + managerName = qmn; + // 设置目标队列 + queueName = quename; + // 创建队列管理器 + connectQM(); + } + + /** + * 程序结束时释放队列管理连接资源 + * + * @throws Exception + */ + private static void destroyEnvironment() throws Exception { + disconnectQM(); + } + + /** + * 获取队列消息,返回信息字符串 + * + */ + private static String receiveMsg() throws Exception { + + String message = null; + // 设置将要连接的队列属性 + int openOptions = MQConstants.MQOO_INPUT_AS_Q_DEF + | MQConstants.MQOO_OUTPUT | MQConstants.MQOO_FAIL_IF_QUIESCING; + + // 设置取消息参数属性 + MQGetMessageOptions gmo = new MQGetMessageOptions(); + gmo.options = MQConstants.MQGMO_SYNCPOINT | MQConstants.MQGMO_WAIT; + // 设置等待时间-1 为无限等待) + gmo.waitInterval = 1000; // 毫秒 + // 打开目标队列 + queue = queueManager.accessQueue(queueName, openOptions); + try { + // 从队列中取出消息 + MQMessage msg = new MQMessage(); + queue.get(msg, gmo); + int dataLength = msg.getDataLength(); + + // 取得消息内容 + message = msg.readStringOfByteLength(dataLength); + // 打印消息内容 + logger.debug("消息内容:\n" + message + "\n"); + queueManager.commit(); + // 消息id 平台唯一标识 + String str = bytes2HexString(msg.messageId) + .toLowerCase(); + logger.debug(">>>>>>>消息ID:" + str); + } catch (MQException e) { + // 回滚事务 + try{ + queueManager.backout(); + }catch(Exception e1){ + logger.error("回滚失败!"); + e1.printStackTrace(); + } + if (2033 == e.getReason()) { + logger.debug("消息已经取完,队列中没有消息!"); + } else { + // 断开重连 + connectQM(); + } + } finally { + // 关闭队列 + if (queue != null) { + queue.close(); + } + } + return message; + } + + private static void connectQM() throws Exception { + // 断开之前的连接 + attempCloseQueueManager(queueManager); + // 创建连接 + queueManager = new MQQueueManager(managerName, env); + } + + private static void disconnectQM() throws Exception { + if (queueManager != null) { + queueManager.disconnect(); + } + } + + private static void attempCloseQueueManager(MQQueueManager qm) { + if (qm == null || !qm.isConnected()) + return; + try { + qm.disconnect(); + } catch (Throwable t) { + + } + } + + /** + * 获取科室字典 + * 服务器IP:192.168.2.180 + * 通道名称:IE.SVRCONN + * 端口:6000 + * 队列管理器:GWO.QM + * 人员队列:OUT.S023.MS024.LQ + * 科室队列:OUT.S023.MS025.LQ + * @return + * @throws Exception + */ + private static List getDepartAndUserMessage(String quename) { + List messages = new ArrayList(); + String host = "200.102.71.201";// 平台地址 + String channal = "IE.SVRCONN";// 通道名称 + String qmn = "GWO.QM";// 目标队列管理器 + boolean flag = true; + // 初始化连接 + try { + initEnvironment(host, channal, qmn, quename); + } catch (Exception e) { + logger.info("getDepartAndUserMessage调用initEnvironment方法出错..."); + e.printStackTrace(); + } + while (flag) { + // 接收消息 + String msg; + try { + msg = receiveMsg(); + if (StringUtils.isNotBlank(msg)) { + messages.add(msg); + } else { + flag = false; + logger.info("接收到科室&人员消息: " + messages.size() + "条。"); + } + } catch (Exception e) { + flag = false; + e.printStackTrace(); + } + } + // 关闭标队列管理器,如果长连接,请不要关闭队列管理器;短连接一定要关闭,不然无法释放连接。 + try { + destroyEnvironment(); + } catch (Exception e) { + logger.info("getDepartMessage调用destroyEnvironment方法出错..."); + e.printStackTrace(); + } + return messages; + } + + /** + * 根据xml结果同步数据 + * + * @param xmlData + */ + private static JSON processData(String xmlData) { + logger.debug("processData xmlData:\n" + xmlData); + try { + // {head:{msgId:'',msgName:''},body:[{}]} + JSON json = CssdUtils.xml2JsonCommon(xmlData); + return json; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 从消息队列获取科室或者人员信息 + * + * @return + * @throws Exception + */ + public static List getDepartAndUserMessageFromMQ(String quequeName) throws Exception { + // 获取科室&人员的消息队列 + List mqList = getDepartAndUserMessage(quequeName); + if ((mqList != null) && (mqList.size() > 0)) { + List voList = new ArrayList(); + for (String mqStr : mqList) { + // 1、xml格式字符串转JSONObject + JSONObject jsonObject = (JSONObject) processData(mqStr); + if (jsonObject != null) { + JSONArray jsonArray = null; + Object bodyObject = jsonObject.opt("body"); + // 2、body标签下有1或多个row,bodyObject作为JSONArray处理 + if (bodyObject != null) { + if (bodyObject instanceof JSONObject) { + jsonArray = new JSONArray(); + jsonArray.add((JSONObject) bodyObject); + } else if (bodyObject instanceof JSONArray) { + jsonArray = (JSONArray) bodyObject; + } + } + if ((jsonArray != null) && (jsonArray.size() > 0)) { + // 3、根据head标签下的msgId字段判断:MS025==科室;MS024==人员 + JSONObject headJSON = jsonObject.optJSONObject("head"); + String msgId = (headJSON == null) ? null : headJSON.optString("msgId"); + for (int i = 0; i < jsonArray.size(); i++) { + // 4、第i个row + JSONObject obj = jsonArray.optJSONObject(i); + if ("MS025".equals(msgId)) {// 科室 + String coding = null; + String name = null; + String parentCoding = null; + coding = obj.optString("organizationid"); + name = obj.optString("name"); + parentCoding = obj.optString("parentorganizationid"); + OrgUnitVo orgUnitVo = new OrgUnitVo(); + orgUnitVo.setCoding(coding); + orgUnitVo.setName(name); + orgUnitVo.setParentCoding(parentCoding); + if (!checkObjAllFieldsIsNull(orgUnitVo)) { + voList.add(orgUnitVo); + } + } else if ("MS024".equals(msgId)) {// 人员 + String coding = null; + String name = null; + String orgUnitCoding = null; + coding = obj.optString("employeeid"); + name = obj.optString("name"); + orgUnitCoding = obj.optString("organizationid"); + UserVo userVo = new UserVo(); + userVo.setCoding(coding); + userVo.setName(name); + userVo.setOrgUnitCoding(orgUnitCoding); + if (!checkObjAllFieldsIsNull(userVo)) { + voList.add(userVo); + } + } else { + + } + } + } + } + } + return voList; + } + return null; + } + + /** + * 判断实体对象是否为空、对象所有非静态属性是否都为空 + * @param object + * @return + */ + public static boolean checkObjAllFieldsIsNull (Object object) { + if (null == object) { + return true; + } + try { + for (Field f : object.getClass().getDeclaredFields()) { + f.setAccessible(true); + if (f.get(object) != null && + StringUtils.isNotBlank(f.get(object).toString()) && + !Modifier.isStatic(f.getModifiers())) { + return false; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + + /** + * 测试用:从xml文件读取xml字符串 + */ + @SuppressWarnings("unused") + private static List xmlFileToStr(String path) { + List strList = new ArrayList(); + String message = null; + try { + SAXReader saxReader = new SAXReader(); + File f = new File(path); + Document doc; + doc = saxReader.read(f); + message = doc.asXML(); + System.out.println(message); + strList.add(message); + } catch (DocumentException e) { + e.printStackTrace(); + } + return strList; + } + + + /** + * 字节数组转换成16机制 + * @param b + * byte[] + * @return String + */ + public static String bytes2HexString(byte[] b) { + String ret = ""; + for (int i = 0; i < b.length; i++) { + String hex = Integer.toHexString(b[i] & 0xFF); + if (hex.length() == 1) { + hex = '0' + hex; + } + ret += hex.toUpperCase(); + } + return ret; + } + +} Index: ssts-web/src/main/webapp/disinfectsystem/config/gzsdbrmyy/spring/HIS.xml =================================================================== diff -u -r30022 -r31655 --- ssts-web/src/main/webapp/disinfectsystem/config/gzsdbrmyy/spring/HIS.xml (.../HIS.xml) (revision 30022) +++ ssts-web/src/main/webapp/disinfectsystem/config/gzsdbrmyy/spring/HIS.xml (.../HIS.xml) (revision 31655) @@ -47,18 +47,6 @@ --> - - - - - - - - - - - + + + + \ No newline at end of file Index: ssts-datasync-default-impl/src/main/java/com/forgon/disinfectsystem/mq/dao/gzsdbrmyy/MQDataDaoImpl.java =================================================================== diff -u --- ssts-datasync-default-impl/src/main/java/com/forgon/disinfectsystem/mq/dao/gzsdbrmyy/MQDataDaoImpl.java (revision 0) +++ ssts-datasync-default-impl/src/main/java/com/forgon/disinfectsystem/mq/dao/gzsdbrmyy/MQDataDaoImpl.java (revision 31655) @@ -0,0 +1,79 @@ +package com.forgon.disinfectsystem.mq.dao.gzsdbrmyy; + +import java.util.List; +import com.forgon.disinfectsystem.datasynchronization.model.OrgUnitVo; +import com.forgon.disinfectsystem.datasynchronization.model.PatientInfoVO; +import com.forgon.disinfectsystem.datasynchronization.model.UserVo; +import com.forgon.disinfectsystem.inventorymanagement.dao.BaseDataDao; + +/** + * MQ队列数据处理类 + * @author zhouPeiMian + * @since 2021-07-07 + * + */ +public class MQDataDaoImpl implements BaseDataDao { + + @Override + public PatientInfoVO[] getAllPatientData() throws Exception { + return null; + } + + @Override + public OrgUnitVo[] getAllOrgUnitVoData() throws Exception { + List list = MQHelper.getDepartAndUserMessageFromMQ(MQHelper.DEPARTMQUEUE); + if (list == null) return null; + OrgUnitVo[] orgUnitVoArr = new OrgUnitVo[list.size()]; + if (list != null && list.size() > 0) { + for (int i = 0; i < list.size(); i++) { + Object obj = list.get(i); + if (obj instanceof OrgUnitVo) { + orgUnitVoArr[i] = (OrgUnitVo) obj; + } + } + } + return orgUnitVoArr; + } + + @Override + public UserVo[] getAllUserVoData() throws Exception { + List list = MQHelper.getDepartAndUserMessageFromMQ(MQHelper.USERMQUEUE); + if (list == null) return null; + UserVo[] userVoArr = new UserVo[list.size()]; + if (list != null && list.size() > 0) { + for (int i = 0; i < list.size(); i++) { + Object obj = list.get(i); + if (obj instanceof UserVo) { + userVoArr[i] = (UserVo) obj; + } + } + } + return userVoArr; + } + + @Override + public Object[] getAllBaseData() { + return null; + } + + @Override + public Object[] getAllDepartAndUserData() { + return null; + } + + @Override + public void invokeMethodOnceAfterStart() throws Exception { + + } + + @Override + public PatientInfoVO[] syncMqPatientInfoByHospitalNumber(String hospitalNum) { + return null; + } + + @Override + public PatientInfoVO[] syncMqPatientInfoByTreatmentNum(String treatmentNum) { + // TODO Auto-generated method stub + return null; + } +}