Spring Boot配置多WebSphere JMS连接监听多队列的方案咨询
解决Spring Boot多WebSphere JMS连接配置问题
嘿,这个问题我熟!你遇到的启动失败本质是Spring Boot自动配置时,发现多个ConnectionFactory bean,没法确定默认用哪个,所以抛出了歧义错误。咱们一步步来搞定多队列收发和多连接的配置,这完全是可行的方案~
1. 先搞定多ConnectionFactory的配置
首先别依赖自动配置的连接工厂了,咱们手动创建每个WebSphere MQ的连接工厂bean,给每个起个独特的名字,还可以用@Primary标记其中一个作为默认(如果你的业务有默认需求的话)。
先在配置文件(比如application.yml)里把多个MQ的参数分开配置,清晰不混乱:
ibm: mq: # 第一个MQ实例配置 first: host: 192.168.1.100 port: 1414 queue-manager: QMGR1 channel: CHANNEL1 username: user1 password: pass1 # 第二个MQ实例配置 second: host: 192.168.1.101 port: 1415 queue-manager: QMGR2 channel: CHANNEL2 username: user2 password: pass2
然后写配置类,绑定这些属性并创建连接工厂:
@Configuration public class MultipleMqConfig { // 绑定第一个MQ的配置 @ConfigurationProperties(prefix = "ibm.mq.first") @Bean("mqFirstProperties") public MQProperties mqFirstProperties() { return new MQProperties(); } // 创建第一个连接工厂 @Bean("mqConnectionFactory1") @Primary // 标记为默认,可选,如果不需要默认可以去掉 public ConnectionFactory mqConnectionFactory1(@Qualifier("mqFirstProperties") MQProperties properties) { MQConnectionFactory factory = new MQConnectionFactory(); try { factory.setHostName(properties.getHost()); factory.setPort(properties.getPort()); factory.setQueueManager(properties.getQueueManager()); factory.setChannel(properties.getChannel()); factory.setTransportType(WMQConstants.WMQ_CM_CLIENT); factory.setStringProperty(WMQConstants.USERID, properties.getUsername()); factory.setStringProperty(WMQConstants.PASSWORD, properties.getPassword()); } catch (MQException e) { throw new RuntimeException("Failed to create first MQ connection factory", e); } return factory; } // 绑定第二个MQ的配置 @ConfigurationProperties(prefix = "ibm.mq.second") @Bean("mqSecondProperties") public MQProperties mqSecondProperties() { return new MQProperties(); } // 创建第二个连接工厂 @Bean("mqConnectionFactory2") public ConnectionFactory mqConnectionFactory2(@Qualifier("mqSecondProperties") MQProperties properties) { MQConnectionFactory factory = new MQConnectionFactory(); try { factory.setHostName(properties.getHost()); factory.setPort(properties.getPort()); factory.setQueueManager(properties.getQueueManager()); factory.setChannel(properties.getChannel()); factory.setTransportType(WMQConstants.WMQ_CM_CLIENT); factory.setStringProperty(WMQConstants.USERID, properties.getUsername()); factory.setStringProperty(WMQConstants.PASSWORD, properties.getPassword()); } catch (MQException e) { throw new RuntimeException("Failed to create second MQ connection factory", e); } return factory; } } // 辅助配置类,用来绑定MQ属性 class MQProperties { private String host; private int port; private String queueManager; private String channel; private String username; private String password; // 生成getter和setter方法 }
2. 配置对应JmsTemplate用于发送消息
每个连接工厂对应一个JmsTemplate,这样你发送消息时可以明确指定用哪个模板:
@Configuration public class JmsTemplateConfig { @Bean("jmsTemplate1") public JmsTemplate jmsTemplate1(@Qualifier("mqConnectionFactory1") ConnectionFactory connectionFactory) { JmsTemplate template = new JmsTemplate(); template.setConnectionFactory(connectionFactory); // 可以添加其他配置,比如默认队列、消息转换器等 return template; } @Bean("jmsTemplate2") public JmsTemplate jmsTemplate2(@Qualifier("mqConnectionFactory2") ConnectionFactory connectionFactory) { JmsTemplate template = new JmsTemplate(); template.setConnectionFactory(connectionFactory); return template; } }
发送消息的时候,注入对应的模板就行:
@Service public class MessageSenderService { @Autowired @Qualifier("jmsTemplate1") private JmsTemplate jmsTemplate1; @Autowired @Qualifier("jmsTemplate2") private JmsTemplate jmsTemplate2; public void sendToQueue1(String message) { jmsTemplate1.convertAndSend("QUEUE_NAME_1", message); } public void sendToQueue2(String message) { jmsTemplate2.convertAndSend("QUEUE_NAME_2", message); } }
3. 配置多队列监听
要监听不同MQ的队列,需要给每个连接工厂创建对应的JmsListenerContainerFactory,然后在@JmsListener注解里指定用哪个容器工厂:
先在配置类里添加容器工厂的配置:
@Configuration @EnableJms public class JmsListenerConfig { @Bean("jmsListenerContainerFactory1") public DefaultJmsListenerContainerFactory jmsListenerContainerFactory1(@Qualifier("mqConnectionFactory1") ConnectionFactory connectionFactory) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); // 可以配置并发数、消息转换器等 factory.setConcurrency("1-3"); return factory; } @Bean("jmsListenerContainerFactory2") public DefaultJmsListenerContainerFactory jmsListenerContainerFactory2(@Qualifier("mqConnectionFactory2") ConnectionFactory connectionFactory) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); factory.setConcurrency("1-3"); return factory; } }
然后写监听方法,明确指定容器工厂:
@Component public class MessageListener { @JmsListener(destination = "QUEUE_NAME_1", containerFactory = "jmsListenerContainerFactory1") public void listenQueue1(String message) { System.out.println("Received from queue1: " + message); // 处理消息逻辑 } @JmsListener(destination = "QUEUE_NAME_2", containerFactory = "jmsListenerContainerFactory2") public void listenQueue2(String message) { System.out.println("Received from queue2: " + message); // 处理消息逻辑 } }
关键注意点
- 如果不需要默认的连接工厂,可以去掉
@Primary注解,但此时所有用到ConnectionFactory的地方都必须用@Qualifier明确指定bean名称。 - 每个MQ的配置参数要准确对应,比如队列管理器、通道名不能错,否则会连接失败。
- 如果需要消息转换器(比如JSON转对象),可以在
JmsTemplate和JmsListenerContainerFactory里统一配置。
这样配置后,Spring Boot启动时就不会再出现连接工厂歧义的问题,而且能同时连接多个不同IP/端口的WebSphere MQ,实现多队列的收发啦~
内容的提问来源于stack exchange,提问作者lalilulelo_1986
相关产品推荐
相关产品推荐

