SpringBoot整合activeMQ遇到的坑,以及整合案例

一、出现以下异常时,需要注意,receive获取消息时不可有返回值,否则循环报此异常
Execution of JMS message listener failed, and no ErrorHandler has been set.

2019-09-17 16:05:06.651  WARN 26416 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer  : Execution of JMS message listener failed, and no ErrorHandler has been set.

org.springframework.jms.listener.adapter.ReplyFailureException: Failed to send reply with payload []; nested exception is javax.jms.InvalidDestinationException: Cannot determine response destination: Request message does not contain reply-to destination, and no default response destination set.
	at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.handleResult(AbstractAdaptableMessageListener.java:285) ~[spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:79) ~[spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736) ~[spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696) ~[spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674) ~[spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318) [spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:257) [spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189) [spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1179) [spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1076) [spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_221]
Caused by: javax.jms.InvalidDestinationException: Cannot determine response destination: Request message does not contain reply-to destination, and no default response destination set.
	at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.getResponseDestination(AbstractAdaptableMessageListener.java:393) ~[spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.getResponseDestination(AbstractAdaptableMessageListener.java:366) ~[spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.handleResult(AbstractAdaptableMessageListener.java:281) ~[spring-jms-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	... 10 common frames omitted

异常源码如下:

@JmsListener(destination="mytopic")
	//未加@SendTo注解引发异常
	public String receviceTopicMsg(TextMessage tm) {
		String str = "";
		try {
			str = tm.getText();
			System.out.println("topic"+ tm.getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return str;
	}

正常是这样:

@JmsListener(destination="mytopic")
	//注:可有返回值,可添加@SendTo注解解决,如果不想加此注解,就必须为void,感谢qq_34651592指教
	@SendTo
	public String receviceTopicMsg(TextMessage tm) {
		try {
			System.out.println("topic"+ tm.getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

二、发布订阅模式需要注意的是Springboot + activeMQ默认情况下是不开启的,需要在消费者配置文件中开启

server:
  port: 8070
spring:
  activemq:
    broker-url: tcp://127.0.0.1:61616
  ##此处配置项便是开启发布订阅模式,开启后队列模式(点对点)不可用
  jms:
    pub-sub-domain: true
queue: myqueue
topic: mytopic

完整的整合案例:
首先是在POM.xml加入依赖文件

  
		org.springframework.boot
		spring-boot-starter-parent
		2.1.0.RELEASE
		 
	
	
		UTF-8
		UTF-8
		1.8
	
	
		
			org.springframework.boot
			spring-boot-starter
		
		
		
			org.springframework.boot
			spring-boot-starter-web
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
			org.springframework.boot
			spring-boot-starter-activemq
		
		
			org.springframework.boot
			spring-boot-devtools
		
	
	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	

生产者配置文件:

server:
  port: 8060
spring:
  activemq:
    broker-url: tcp://127.0.0.1:61616
queue: myqueue
topic: mytopic

配置类

/**
 * 	队列模式,点对点配置类,一条消息只能被一个消费者获取
 * @ClassName: QueueConfig
 * @Description: TODO
 * @author: dufen
 * @date: 2019年9月17日 下午2:38:34
 */
@Component
public class QueueConfig {
	@Value(value="${queue}")
	private String queue;
	@Bean
	public Queue getQueue() {
		return new ActiveMQQueue(queue);
	}
}
/**
 * 	发布订阅者模式,一条消息可以被多人获取,前提是必须先开启消费者,再开启生产者,否则,消息会被作废
 * @ClassName: TopicConfig
 * @Description: TODO
 * @author: dufen
 * @date: 2019年9月17日 下午4:16:57
 */
@Component
public class TopicConfig {
	@Value(value="${topic}")
	private String topic;
	@Bean
	public Topic getTopic() {
		return new ActiveMQTopic(topic);
	}
}

业务层

/**
 * 发送信息业务层
 * @ClassName: SendMessageService
 * @Description: TODO
 * @author: dufen
 * @date: 2019年9月17日 下午4:18:38
 */
@Component
public class SendMessageService {
	@Autowired
	private JmsMessagingTemplate jmsMessagingTemplate;
	@Autowired
	private Queue queue;
	@Autowired
	private Topic topic;
	/**
	 * 发送队列消息
	 * @Title: sendQueueMsg
	 * @Description: TODO
	 * @param msg
	 * @return: void
	 */
	public void sendQueueMsg(String msg) {
		jmsMessagingTemplate.convertAndSend(queue, msg);
	}
	/**
	 * 发布订阅模式·发送消息
	 * @Title: sendTopicMsg
	 * @Description: TODO
	 * @param msg
	 * @return: void
	 */
	public void sendTopicMsg(String msg) {
		jmsMessagingTemplate.convertAndSend(topic, msg);
	}
}

控制层

/**
 * 控制层
 * @ClassName: MsgContoller
 * @Description: TODO
 * @author: dufen
 * @date: 2019年9月17日 下午4:20:31
 */
@RestController
public class MsgContoller {
	@Autowired
	private SendMessageService sendMessageService;

	@RequestMapping("/sendQueueMsg")
	public String sendQueueMsg(@RequestParam(name="msg")String msg) {
		sendMessageService.sendQueueMsg(msg);
		return msg;
	}
	@RequestMapping("/sendTopicMsg")
	public String sendTopicMsg(@RequestParam(name="msg")String msg) {
		sendMessageService.sendTopicMsg(msg);
		return msg;
	}
}

生产者服务器启动类

@SpringBootApplication
public class ProviderApp {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SpringApplication.run(ProviderApp.class, args);
	}

}


消费者配置文件

server:
  port: 8070
spring:
  activemq:
    broker-url: tcp://127.0.0.1:61616
 #此处开启发布订阅者模式,开启后,队列模式无法获取消息
  jms:
    pub-sub-domain: true

/**
 * 消费者监听获取消息类
 * @ClassName: ReceiveMessageService
 * @Description: TODO
 * @author: dufen
 * @date: 2019年9月17日 下午4:26:55
 */
@Component
public class ReceiveMessageService {
	@JmsListener(destination="myqueue")
	//注:此处方法不可有返回值
	public void receviceMsg(TextMessage tm) {
		String str = "";
		try {
			str = tm.getText();
			System.out.println("queue"+ tm.getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	@JmsListener(destination="mytopic")
	//注:此处方法不可有返回值
	public void receviceTopicMsg(TextMessage tm) {
		String str = "";
		try {
			str = tm.getText();
			System.out.println("topic"+ tm.getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}
@SpringBootApplication
public class ConsumerApp {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SpringApplication.run(ConsumerApp.class, args);
	}

}

整合完成,还有定时调度,
直接在发送消息类名之上加上@EnableScheduling,
发送消息的方法之上加上注解@Scheduled(fixedDelay = 5000),fixedDelay单位为毫秒

你可能感兴趣的:(Java)