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;
    }
}
View Code

 

posted @ 2020-04-04 16:11  silencemaker1221  阅读(377)  评论(0编辑  收藏  举报