IBMMQ之工具类
package com.citic.util; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FilenameFilter; import java.io.IOException; import java.util.HashMap; import java.util.regex.Pattern; import com.citic.util.comm.*; import com.citic.util.MD5Util; import com.ibm.mq.MQEnvironment; import com.ibm.mq.MQException; import com.ibm.mq.MQGetMessageOptions; import com.ibm.mq.MQMessage; import com.ibm.mq.MQPutMessageOptions; import com.ibm.mq.MQQueue; import com.ibm.mq.MQQueueManager; import com.ibm.mq.constants.MQConstants; /** * 本类主要功能:实现MQ文件的发送和接收 * 因主要是对同一个MQ配置,所以相同的参数采用静态变量,如队列管理器创建非常占用时间 * ,所以静态处理,不管是发送还是接收都采用同一个 * runGoupReceier(int receivesize) 根据传入变量来指定获取MQ条数(可在config.properties中配置) * runGoupReceier() 默认获取MQ条数20 * runGoupSender(String[] filelist) 根据数组中列出的全部文件名发送 * runGoupSender(String pattern) 根据模式匹配发送数据 * @author db2admin * */ public class MQUtil implements IConstants{ final static int BUFFER_LEN = 1024 * 1024; // 定义发送文件的大小 private static MQQueueManager qmgr; // 连接到队列管理器 private static MQQueue queue; // 传输队列 private static String iqueueName,oqueueName; // 队列名称 private static String host = "127.0.0.1"; // 队列名称 private static String port = "1414"; // 侦听器的端口号 private static String channel = "SYSTEM.BKR.CONFIG"; // 通道名称 private static String qmgrName; // 队列管理器 private MQMessage message; // 创建消息缓冲 private static MQPutMessageOptions pmo; // 设置获取消息选项 private static MQGetMessageOptions gmo; // 设置获取消息选项 private static boolean rewriteflag=false; //收取MQ的文件时候是否需要对重复文件进行收取,false则不收 private static int opnOptn=0; private static String ccsid ; private String file_dir = null; private static String dval=ConfigFileUtil.getValue("debuglevel"); private static int debuglevel=("".equals(dval)?ALL:Integer.parseInt(dval)); private char flag='S'; //S/R 发送或接收 private String pstr; private File[] flist; private static int readpertime = 20; // 每次读取MQ数量,默认为20条 private int readcnt=0; //每个周期实际读取MQ信息数,<=readpertime private String[] strarr = null; private HashMap<String,String> datahm=null; private HashMap<String,String> md5map=new HashMap<String, String>(); private String charset=ConfigFileUtil.getValue("charset"); //实现对队列管理器的初始化 private static void getInstance(){ if(qmgr==null){ /* 连接到队列管理器 */ initproperty(); try { qmgr = new MQQueueManager(qmgrName); } catch (MQException e) { CommFun.log(ERR, "创建"+qmgrName+"失败!退出!"); e.printStackTrace(); throw new RuntimeException(); } //经监控,此步大概需要10秒左右,所以重点优化 } CommFun.log(INFO, "连接" + qmgrName + "成功![host:" + host + ",port:" + port + ",qmgrName:" + qmgrName + ",iqueueName:" + iqueueName + ",oqueueName:" + oqueueName + ",channel:" + channel + ",ccsid:" + ccsid + "]"); } //队列初始化中 private void getInstance(String sflag){ if (!"".equals(sflag) && sflag != null && sflag.length() > 0) { flag = sflag.charAt(0); } getInstance(); } private void init(){ String queuename=""; file_dir = ConfigFileUtil.getInstance().getPathName(); if(flag=='S'){ /* 设置队列打开选项以输 */ opnOptn = MQConstants.MQOO_FAIL_IF_QUIESCING | MQConstants.MQOO_OUTPUT; // 只是单纯的收取数据,非破坏性 // opnOptn = MQConstants.MQOO_BROWSE // | MQConstants.MQOO_FAIL_IF_QUIESCING // | MQConstants.MQOO_INQUIRE; queuename = oqueueName; file_dir += "send"; } else { /* 设置队列打开选项以输 */ opnOptn = MQConstants.MQOO_INPUT_AS_Q_DEF | MQConstants.MQOO_FAIL_IF_QUIESCING | MQConstants.MQOO_INQUIRE; queuename = iqueueName; file_dir += "receive"; } try { queue = qmgr.accessQueue(queuename, opnOptn, null, null, null); CommFun.log(INFO, "queue's name:" + queuename + ",file_dir:[" + file_dir + "]"); } catch (MQException e) { CommFun.log(ERR, "队列访问失败:"+e.getReason()); commit(); throw new RuntimeException(); } } /** * 发送的单条主程序 * * @throws Exception */ private void sendMessages(String filename) { /* 设置放置消息选项 */ message = new MQMessage(); pmo = new MQPutMessageOptions(); pmo.options = MQConstants.MQPMO_LOGICAL_ORDER + MQConstants.MQPMO_SYNCPOINT; message.characterSet=Integer.parseInt(ccsid);; try{ FileInputStream fis = new FileInputStream(new File(filename)); byte buffer[] = new byte[fis.available()]; int count = 0; while (true) { count = fis.read(buffer); if (count == -1) { break; } message.write(buffer); System.out.println(buffer.length); if (count < BUFFER_LEN) { System.out.println("count:"+count); } queue.put(message, pmo); // qmgr.commit(); } fis.close(); }catch (MQException mqe) { CommFun.log(ERR, "["+filename+"]MQ-put信息失败!"); mqe.printStackTrace(); commit(); throw new RuntimeException(); } catch (FileNotFoundException e) { CommFun.log(ERR, "["+filename+"]文件不存在"); e.printStackTrace(); commit(); throw new RuntimeException(); } catch (IOException e) { CommFun.log(ERR, "["+filename+"]文件操作错误"); e.printStackTrace(); commit(); throw new RuntimeException(); } } //批量发送 private void runGoupSender() { //0.获取队列管理器 getInstance("S"); //1.初始化队列 init(); String filePath = file_dir; File file = new File(filePath); File[] filelist=flist; // pstr="PSIS(900|802|1.*).*_S\\.xml"; if (pstr != null && !"".equals(pstr)) { filelist = file.listFiles(new FilenameFilter() { private Pattern pattern = Pattern.compile(pstr .replace("_S", "") + ".*_S\\.xml"); @Override public boolean accept(File dir, String name) { return pattern.matcher(name).matches(); } }); } int fcount=1; for (File f : filelist) { CommFun.log(debuglevel, f.getAbsolutePath()); //sendMessages(filePath + File.separator + f.getName()); sendMessages(f.getAbsolutePath()); CommFun.log(INFO, "MQ发送第["+filelist.length+":"+(fcount++)+"]个文件完毕!"); } //9.发送后处理 // commit(); System.out.println("\n Messages successfully Send "); } //主体获取MQ信息,对出现MD5值重复的数据进行处理,原则上全部收取下来,但是并不写入 private void getGroupMessages() { /* 设置获取消息选项 */ CommFun.log(debuglevel); gmo = new MQGetMessageOptions(); CommFun.log(debuglevel); gmo.options = MQConstants.MQGMO_FAIL_IF_QUIESCING + MQConstants.MQGMO_SYNCPOINT + MQConstants.MQGMO_WAIT + MQConstants.MQGMO_ALL_MSGS_AVAILABLE + MQConstants.MQGMO_LOGICAL_ORDER; /* 设置等待时间限制 */ gmo.waitInterval = 5000; gmo.matchOptions = MQConstants.MQMO_MATCH_GROUP_ID; int cnt = 0; int counter=0; int qdepth=getQueueDepth(); CommFun.log(debuglevel,"depth:"+getQueueDepth()); /** * 20170515添加对接收的MD5值当天数据载入,重复文件不再接收 * 当前目录MD5.txt,其中的格式如FileOperation中 * 的stringbuffer2file(StringBuffer[] stb, String filename)方法 * "filename:"+filename+",strmd5:"+strmd5+",filemd5:"+filemd5 */ String md5file=file_dir + File.separator + md5filename; if(qdepth==0){ CommFun.log(debuglevel, "队列深度为0,不需要载入MD5文件"); }else{ CommFun.log(debuglevel, "MD5文件:"+md5file); md5map=FileOperation.loadMD5txt(file_dir); if(md5map==null||md5map.size()==0){ CommFun.log(debuglevel, "MD5文件:"+md5file+"不存在!"); } } /* 处理组消息 */ String fileName; datahm=new HashMap<String, String>(); while (cnt < readpertime) { try{ /* 创建消息缓冲 */ message = new MQMessage(); queue.get(message, gmo); CommFun.log(INFO,"cnt:"+cnt+",read:"+readpertime); int msgLength = message.getMessageLength(); byte[] buffer = new byte[msgLength]; CommFun.log(INFO,"msgLength:" + msgLength); message.readFully(buffer); String st1 = new String(buffer, ("".equals(charset)?"UTF-8":charset)).replaceAll("\\r", ""); CommFun.log(INFO, "获取MQ数据:第"+(counter++)+"次读取:当前有效条数:" + cnt + ":buffer:[" + buffer + "],str1:[" + st1.substring(0, 200) + "]"); // strarr[cnt]=new String(buffer,"GBK"); String filenameEx=file_dir + File.separator + "SUPIS" + CommFun.strNowRand() + ".xml"; CommFun.log(0,"strarr:" + cnt + ":[" + st1 + "]:inMsg:["+message+"]"); message.clearMessage(); String md5str=MD5Util.getMD5String(st1); if(md5map.containsKey(md5str)){ CommFun.log(INFO, ":MD5["+md5str+"]根据MD5值计算重复,跳过!"); //MD5重复文件控制写入,从MQ上收取下来的数据很多重复,所以进行控制 if(rewriteflag){ StringBuffer[] sbf = { new StringBuffer(st1) }; FileOperation.stringbuffer2file(sbf, filenameEx); } continue; } //进行MD5值计算,用来对以后的数据去重 String oldvalue=ConfigFileUtil.getValue("md5"); ConfigFileUtil.setValue("md5", "true"); StringBuffer[] sbf = { new StringBuffer(st1) }; FileOperation.stringbuffer2file(sbf, filenameEx,md5str); ConfigFileUtil.setValue("md5", oldvalue); //strarr[cnt] = st1; datahm.put(st1, filenameEx); md5map.put(md5str,""); readcnt=++cnt; }catch(MQException mqe){ if(mqe.reasonCode!=MQConstants.MQRC_NO_MSG_AVAILABLE){ //如果出错,则进行重置参数 cnt=0; readcnt=0; strarr=null; datahm=null; try { CommFun.log(ERR, "出问题,返回:"+mqe.getMessage()); qmgr.backout(); } catch (MQException e) { CommFun.log(ERR, "出问题,返回:"+e.getMessage()); commit(); e.printStackTrace(); throw new RuntimeException(); } }else{ readcnt=cnt; // commit(); CommFun.log(INFO, "正常结束,队列取完,readcnt为:"+readcnt); break; } }catch(Exception e){ CommFun.log(ERR,"出错:"+e.getMessage()); e.printStackTrace(); commit(); throw new RuntimeException(); } CommFun.log(debuglevel); } CommFun.log(debuglevel,"字符串数据个数为:"+datahm.size()+",cnt:"+cnt+",队列中还剩余:["+Math.max(0,(qdepth-counter))+"]条!"); } /** * MQConfig.getInstance(key) 1生产2测试 */ private static void initproperty() { String mqkey = ConfigFileUtil.getValue("MQKEY"); mqkey = (mqkey == "" ? "2" : mqkey); if (iqueueName == null) { qmgrName = ConfigFileUtil.getValue(mqkey+"_MQ_MANAGER"); iqueueName = ConfigFileUtil.getValue(mqkey+"_MQ_IQUEUE_NAME"); oqueueName = ConfigFileUtil.getValue(mqkey+"_MQ_OQUEUE_NAME"); channel = ConfigFileUtil.getValue(mqkey+"_MQ_CHANNEL"); host = ConfigFileUtil.getValue(mqkey+"_MQ_HOST_NAME"); port = ConfigFileUtil.getValue(mqkey+"_MQ_PROT"); ccsid = ConfigFileUtil.getValue(mqkey+"_MQ_CCSID"); } /* 为客户机连接设置MQEnvironment属性 */ MQEnvironment.hostname = host; MQEnvironment.channel = channel; MQEnvironment.port = Integer.parseInt(port); MQEnvironment.CCSID = Integer.parseInt(ccsid); } //发送完后续处理 public void commit() { CommFun.log(debuglevel, "提交后处理!");// if (queue != null && queue.isOpen()) { CommFun.log(debuglevel, "提交后处理,关闭队列!"); try { queue.close(); } catch (MQException e) { CommFun.log(ERR); e.printStackTrace(); throw new RuntimeException(); } } if (qmgr != null && qmgr.isConnected()) { CommFun.log(INFO, "提交后处理,关闭队列管理器!"); try { qmgr.commit(); qmgr.disconnect(); } catch (MQException e) { CommFun.log(debuglevel); e.printStackTrace(); throw new RuntimeException(); } } CommFun.log(debuglevel, "提交后处理成功!"); } //获取队列深度,一般接收时使用 public Integer getQueueDepth() { Integer depth = 0; try { if (queue != null && queue.isOpen()) { depth = queue.getCurrentDepth(); } } catch (MQException e) { e.printStackTrace(); commit(); throw new RuntimeException(); } return depth; } //主体调用程序 //批量发送1:通过通配符 public void runGoupSender(String pattern) { pstr=pattern; runGoupSender(); } //批量发送2:通过数组 public void runGoupSender(String[] filelist) { CommFun.log(INFO, "############"+filelist.length); if (filelist.length > 0) { flist = new File[filelist.length]; for (int i = 0; i < filelist.length && filelist[i] != null && !"".equals(filelist[i]); i++) { CommFun.log(debuglevel, filelist[i]); flist[i] = new File(filelist[i]); } } runGoupSender(); } //接收MQ,设置接收个数 public HashMap<String,String> runGoupReceier(int inputSize) { if (inputSize > 0) { readpertime = inputSize; } return runGoupReceier(); } //获取数据 public HashMap<String,String> runGoupReceier() { // strarr = new String[readpertime]; CommFun.log(INFO, "此次所取的MQ条数为:[" + readpertime + "]"); // 0.获取队列管理器 getInstance("R"); // 1.初始化队列 init(); getGroupMessages(); CommFun.log(debuglevel); //String[] strarr1 = new String[readcnt]; //System.arraycopy(strarr, 0, strarr1, 0, readcnt); return datahm; } }