Springboot配置IBM MQ消息队列监听

背景:服务端提供13个消息队列,做为客户端需要从队列中消费消息,刚开始使用死循环去消费,消费到一定量级后提示2044,扒了一下资料,发现可能是因为循环次数过多导致,然后开始研究队列监听方式来获取数据。

使用队列监听需要在原来基础上新建两个类,直接上代码:

导入jar包(其中和MQ相关的jar包以自己的为准,不要直接使用我的,我的MQ的jar包中7.X版本是服务端提供的):

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jms</artifactId>
</dependency>
<dependency>
    <groupId>javax.jms</groupId>
    <artifactId>javax.jms-api</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
	<groupId>com.ibm.mq</groupId>
	<artifactId>mq</artifactId>
	<version>7.0.1.3</version>
	<scope>system</scope>
	<systemPath>${project.basedir}/lib/com.ibm.mq-7.0.1.3.jar</systemPath>
</dependency>
<dependency>
	<groupId>com.ibm.mq</groupId>
	<artifactId>commonservices</artifactId>
	<version>7.0.1.3</version>
	<scope>system</scope>
    <systemPath>${project.basedir}/lib/com.ibm.mq.commonservices-7.0.1.3.jar</systemPath>
</dependency>
<dependency>
	<groupId>com.ibm.mq</groupId>
	<artifactId>com.ibm.mq.allclient</artifactId>
	<version>9.0.5.0</version>
</dependency>
<dependency>
	<groupId>com.ibm.mq</groupId>
	<artifactId>headers</artifactId>
	<version>7.0.1.3</version>
	<scope>system</scope>
    <systemPath>${project.basedir}/lib/com.ibm.mq.headers-7.0.1.3.jar</systemPath>
</dependency>
<dependency>
	<groupId>com.ibm.mq</groupId>
	<artifactId>jmqi</artifactId>
	<version>7.0.1.3</version>
	<scope>system</scope>
	<systemPath>${project.basedir}/lib/com.ibm.mq.jmqi-7.0.1.3.jar</systemPath>
</dependency>
<dependency>
	<groupId>com.ibm.mq</groupId>
	<artifactId>pcf</artifactId>
	<version>7.0.1.3</version>
	<scope>system</scope>
	<systemPath>${project.basedir}/lib/com.ibm.mq.pcf-7.0.1.3.jar</systemPath>
</dependency>
<dependency>
	<groupId>commons</groupId>
	<artifactId>codec</artifactId>
	<version>1.6</version>
	<scope>system</scope>
	<systemPath>${project.basedir}/lib/commons-codec-1.6.jar</systemPath>
</dependency>

MQConfig.class(MQ配置):

package com.zpd.listener;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jms.connection.CachingConnectionFactory;
import org.springframework.jms.connection.JmsTransactionManager;
import org.springframework.jms.core.JmsOperations;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.transaction.PlatformTransactionManager;
 
import com.ibm.mq.jms.MQQueueConnectionFactory;
import com.ibm.msg.client.wmq.WMQConstants;

import lombok.extern.slf4j.Slf4j;
 
@Configuration
@Slf4j
public class JmsConfig {
	
    //此处将MQ队列配置的信息直接写到了代码中,如果写在了配置文件中,可以通过@Value来获取
    //@Value("${project.mq.host}")
    private String host = "...";
    
    //@Value("${project.mq.port}")
    private Integer port = 6000;
    
    //@Value("${project.mq.ccsid}")
    private Integer ccsid = 1208;
    
    //@Value("${project.mq.queue-manager}")
    private String queueManager = "...";
    
    //@Value("${project.mq.channel}")
    private String channel = "...";
    
    //@Value("${project.mq.receive-timeout}")
    private long receiveTimeout = 20000L;
    
    @Bean
    public MQQueueConnectionFactory mqQueueConnectionFactory() {
        MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
        mqQueueConnectionFactory.setHostName(host);
        try {
        	mqQueueConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
            mqQueueConnectionFactory.setCCSID(ccsid);
            mqQueueConnectionFactory.setChannel(channel);
            mqQueueConnectionFactory.setPort(port);
            mqQueueConnectionFactory.setQueueManager(queueManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mqQueueConnectionFactory;
    }
    
    //此处因为消息队列不需要通过用户名和密码去获取,所以直接将mqQueueConnectionFactory注入到了缓存配置中,如果需要用到用户名和密码,可以去参考其他资料
    @Bean
    @Primary
    public CachingConnectionFactory cachingConnectionFactory(MQQueueConnectionFactory mqQueueConnectionFactory) {
    	CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
        cachingConnectionFactory.setTargetConnectionFactory(mqQueueConnectionFactory);
        cachingConnectionFactory.setSessionCacheSize(500);
        cachingConnectionFactory.setReconnectOnException(true);
        return cachingConnectionFactory;
    }
    
    @Bean
    public PlatformTransactionManager jmsTransactionManager(CachingConnectionFactory cachingConnectionFactory) {
        JmsTransactionManager jmsTransactionManager = new JmsTransactionManager();
        jmsTransactionManager.setConnectionFactory(cachingConnectionFactory);
        return jmsTransactionManager;
    }
    
    //如果只是获取消息,此处无需配置
    @Bean
    public JmsOperations jmsOperations(CachingConnectionFactory cachingConnectionFactory) {
        JmsTemplate jmsTemplate = new JmsTemplate(cachingConnectionFactory);
        jmsTemplate.setReceiveTimeout(receiveTimeout);
        return jmsTemplate;
    }
}

MQListener.class(MQ监听):

package com.zpd.listener;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsOperations;
import org.springframework.jms.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Component;

import com.zpd.service.DataService;
import com.zpd.utils.JDBCUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class MQListener extends MessageListenerAdapter {
	private static final DataService dataService = new DataService();
	
	@Autowired
	JmsOperations jmsOperations;
	
	/*
	 * BS002队列监听
	 * @author chengjunyu 
	 * @date 2019-11-05 12:48:57
	 * @param
	 */
    @JmsListener(destination = "BS002")
    public void onMessageBS002(Message message) {
        String msgStr ="";
        String sourceFrom = "BS002";
        try {  //JmsListener收到消息后,会自动封装成自己特有的数据格式,可以用TextMessage来解析原始消息
            TextMessage msg = (TextMessage) message;
            msgStr = msg.getText();
            log.info("从队列BS002中获取的消息内容:" + msgStr);
            //将消息写入/zpd/sc_interface/路径下
            saveMessageToFile(sourceFrom, msgStr);
            dataService.getMessageFromBS002(msgStr);
        } catch (JMSException e) {
            log.error("从队列BS002中接收消息异常!", e);
        } catch (Exception e) {
        	saveException(sourceFrom, msgStr, e);
		}
    }
	
    /*
     * BS004队列监听
     */
    @JmsListener(destination = "BS004")
    public void onMessageBS004(Message message) {
        String msgStr ="";
        String sourceFrom = "BS004";
        try {  //JmsListener收到消息后,会自动封装成自己特有的数据格式,可以用TextMessage来解析原始消息
            TextMessage msg = (TextMessage) message;
            msgStr = msg.getText();
            log.info("从队列BS004中获取的消息内容:" + msgStr);
            //将消息写入/zpd/sc_interface/路径下
            saveMessageToFile(sourceFrom, msgStr);
            dataService.getMessageFromBS004(msgStr);
        } catch (JMSException e) {
            log.error("从队列BS004中接收消息异常!", e);
        } catch (Exception e) {
        	saveException(sourceFrom, msgStr, e);
		}
    }
    
    /*
     * BS005队列监听
     */
    @JmsListener(destination = "BS005")
    public void onMessageBS005(Message message) {
        String msgStr ="";
        String sourceFrom = "BS005";
        try {  //JmsListener收到消息后,会自动封装成自己特有的数据格式,可以用TextMessage来解析原始消息
            TextMessage msg = (TextMessage) message;
            msgStr = msg.getText();
            log.info("从队列BS005中获取的消息内容:" + msgStr);
            //将消息写入/zpd/sc_interface/路径下
            saveMessageToFile(sourceFrom, msgStr);
            dataService.getMessageFromBS005(msgStr);
        } catch (JMSException e) {
            log.error("从队列BS005中接收消息异常!", e);
        } catch (Exception e) {
        	saveException(sourceFrom, msgStr, e);
		}
    }

	
	/*
	 * 保存异常信息到数据库中
	 * @Author chengjunyu
	 * @date 2019-11-05 12:56:35
	 */
	public void saveException(String sourceFrom, String msgStr, Exception e) {
		Connection connection = JDBCUtils.getConnection();
		PreparedStatement pstmt = null;
		String exceptionSql = "insert into run_log values (null,?,?,?,'"+dataService.getNowTime()+"')";
		try {
			pstmt = connection.prepareStatement(exceptionSql);
			pstmt.setString(1, sourceFrom);
			pstmt.setString(2, msgStr);
			pstmt.setString(3, getExceptionInfo(e));
			pstmt.execute();
		} catch (SQLException e2) {
			log.info(sourceFrom + "保存错误信息异常:" + e2);
		} finally {
			if(pstmt != null) {
				try {
					pstmt.close();
				} catch (SQLException e1) {
					log.info(sourceFrom + "关闭预编译失败,原因为:" + e1);
				}
			}
			if(connection != null) {
				try {
					connection.close();
				} catch (SQLException e1) {
					log.info(sourceFrom + "关闭数据库连接失败,原因为:" + e1);
				}
			}
		}
	}
	
	/*
	 * 将异常信息转换为字符串
	 * @Author chengjunyu
	 * @date 2019-11-05 12:56:59
	 */
	public String getExceptionInfo(Throwable t) {
	    StringWriter stringWriter= new StringWriter();
	    PrintWriter writer= new PrintWriter(stringWriter);
	    t.printStackTrace(writer);
	    StringBuffer buffer= stringWriter.getBuffer();
	    return buffer.toString();
	}
	
	/*
	 * 将消息内容保存到磁盘文件上
	 * @Author chengjunyu
	 * @date 2019-11-05 12:57:28
	 */
	public void saveMessageToFile(String sourceFrom, String msgStr) {
		try {
			String dirPathOuter = "/zpd/sc_interface/" + sourceFrom;
			File dirOuter = new File(dirPathOuter);
			if(!dirOuter.exists()) {
				dirOuter.mkdirs();
			}
			
			String dirPathInner = dirPathOuter + "/" + getDate();
			File dirInner = new File(dirPathInner);
			if(!dirInner.exists()) {
				dirInner.mkdirs();
			}
			String filePath = dirPathInner + "/" + sourceFrom + "_" + getTime() + ".xml";
			File txt = new File(filePath);
			if (!txt.exists()) {
				txt.createNewFile();
			}
			byte bytes[] = new byte[512];
			bytes = msgStr.getBytes();
			FileOutputStream fos = new FileOutputStream(txt);
			fos.write(bytes);
			fos.flush();
			fos.close();
		} catch (IOException e) {
			log.info("保存信息到文件产生异常:" + e);
		}
	}
	
	public String getDate() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		Date date = new Date();
		String dateStr = sdf.format(date);
		return dateStr;
	}
	
	public String getTime() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		Date date = new Date();
		String dateStr = sdf.format(date);
		return dateStr;
	}
}

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您好,针对您的问题,可以使用Spring Boot的JMS支持来整合IBMMQ,并通过配置多个连接工厂来监听多个服务器的消息。具体步骤如下: 1. 在pom.xml文件中添加如下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency> ``` 2. 配置IBMMQ连接工厂 在application.properties文件中添加如下配置: ``` spring.jms.pub-sub-domain=true spring.jms.listener.auto-startup=true spring.jms.listener.concurrency=1 spring.jms.listener.max-concurrency=10 # 第一个IBMMQ连接工厂配置 spring.jms.ibm.mq.queue-manager=QM1 spring.jms.ibm.mq.channel=CHANNEL1 spring.jms.ibm.mq.conn-name=host1(1414) # 第二个IBMMQ连接工厂配置 spring.jms.ibm.mq.queue-manager=QM2 spring.jms.ibm.mq.channel=CHANNEL2 spring.jms.ibm.mq.conn-name=host2(1414) ``` 其中,spring.jms.ibm.mq.*为IBMMQ连接工厂的配置项,可根据实际情况进行修改。 3. 监听IBMMQ消息 通过在Spring Boot中配置JMS监听器来监听IBMMQ消息。可以使用@JmsListener注解来指定监听队列名称。 ``` @Component public class IBMMQListener { @JmsListener(destination = "QUEUE1") public void onMessage1(Message message) { // 处理消息 } @JmsListener(destination = "QUEUE2") public void onMessage2(Message message) { // 处理消息 } } ``` 其中,@JmsListener注解中的destination属性为队列名称,可以根据实际情况进行修改。 通过以上步骤,即可实现Spring Boot整合IBMMQ,同时监听多个服务器消息
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值