mq ist in Warteschlangen unterteilt (Warteschlangenmodus, der Produzent erstellt eine Nachricht, die nur von einem Verbraucher verwendet werden kann) (Veröffentlichungs- / Abonnementmodus, der Produzent erstellt eine Nachricht, die von mehreren Verbrauchern verwendet werden kann).
Konfiguration von application.properties
# http port
server.port=9090
env.host.mq=192.168.46.128
#========================================================MQ=================================================#
spring.activemq.broker-url=tcp://${env.host.mq}:61616
spring.activemq.user=admin
spring.activemq.password=admin
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=50
#MQ白名单信任
spring.activemq.packages.trust-all=true
mq Konfigurationsklasse
package com.wl.dubbo.blog.mq;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import javax.jms.ConnectionFactory;
import javax.jms.Queue;
/**
* Created by wl on 2017/12/28.
*/
@Configuration
@EnableJms
public class MqConfig {
@Value("${spring.activemq.broker-url}")
private String broker_url;
@Value("${spring.activemq.user}")
private String jmsUser;
@Value("${spring.activemq.password}")
private String jsmPass;
private static final String QUEUE_NAME_ = "queue";
private static final String TOPIC_NAME = "orders";
@Bean("queue")
public Queue queueQueue(){
return new ActiveMQQueue(QUEUE_NAME_);
}
@Bean("topicQueue")
public ActiveMQTopic topicQueue(){
return new ActiveMQTopic(TOPIC_NAME);
}
@Bean(name = "activeMQConnectionFactory")
public ActiveMQConnectionFactory activeMQConnectionFactory(){
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(jmsUser,jsmPass,broker_url);
activeMQConnectionFactory.setTrustAllPackages(true);
return activeMQConnectionFactory;
}
@Bean(name = "queueListenerFactory")
public JmsListenerContainerFactory<?> queueListenerFactory(ConnectionFactory activeMQConnectionFactory){
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setPubSubDomain(false);
factory.setConnectionFactory(activeMQConnectionFactory);
return factory;
}
@Bean(name = "topicListenerFactory")
public JmsListenerContainerFactory<DefaultMessageListenerContainer> topicListenerFactory(ConnectionFactory activeMQConnectionFactory){
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setPubSubDomain(true);
factory.setConnectionFactory(activeMQConnectionFactory);
return factory;
}
@Bean
public JmsMessagingTemplate jmsMessagingTemplate(ConnectionFactory activeMQConnectionFactory){
return new JmsMessagingTemplate(activeMQConnectionFactory);
}
}
veröffentlichen
package com.wl.dubbo.blog.mq;
import org.apache.activemq.command.ActiveMQTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;
import javax.jms.Queue;
/**
* Created by wl on 2017/12/28.
*/
@Component
public class ActiveMQSendService {
private static final Logger logger = LoggerFactory.getLogger(ActiveMQSendService.class);
private JmsMessagingTemplate jmsMessagingTemplate;
private Queue queueQueue;
private ActiveMQTopic activeMQTopic;
@Autowired
public ActiveMQSendService(JmsMessagingTemplate jmsMessagingTemplate,
Queue queueQueue,
ActiveMQTopic topicQueue){
this.jmsMessagingTemplate = jmsMessagingTemplate;
this.queueQueue = queueQueue;
this.activeMQTopic = topicQueue;
}
public void sendQueueMessage(String message){
logger.info("send queue:{}",message);
jmsMessagingTemplate.convertAndSend(queueQueue,message);
}
public void sendTopicMessage(String message){
logger.info("send topic:{}",message);
jmsMessagingTemplate.convertAndSend(activeMQTopic,message);
}
}
Verbraucher
package com.wl.dubbo.blog.mq;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
/**
* Created by wl on 2017/12/28.
*/
@Component
public class ReceiverService {
private static final Logger logger = LoggerFactory.getLogger(ReceiverService.class);
@JmsListener(destination = "queue",containerFactory = "queueListenerFactory")
public void receiveTestQueue(String receiveStr) throws JMSException {
logger.info("=======================queue:{}",receiveStr);
}
@JmsListener(destination = "orders",containerFactory = "topicListenerFactory" )
public void receiveTopicQueue(String receiveStr) throws JMSException {
logger.info("=======================orders:{}",receiveStr);
}
}
Starten Sie den Unterricht
package com.wl.dubbo.blog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
/**
* Created by wl on 2018/8/3.
*/
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class, //不使用数据库
},scanBasePackages = "com.wl")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(BlogApplication.class);
public static void main(String[] args) {
SpringApplication app = new SpringApplication(BlogApplication.class);
app.setWebEnvironment(true);
app.run(args);
logger.info("application init success");
}
}
Testklasse
package com.wl.dubbo.blog;
import com.wl.dubbo.blog.mq.ActiveMQSendService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Created by wl on 2018/8/27.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
@Autowired
private ActiveMQSendService activeMQSendService;
@Test
public void testSendQueue(){
activeMQSendService.sendQueueMessage("queue===============");
}
@Test
public void testSendTopic(){
activeMQSendService.sendTopicMessage("topic================");
}
}
Die obige Themennachricht ist nicht dauerhaft. Wenn die Themennachricht vor dem Start der konsumierenden Anwendung gesendet wird, kann der Konsument die Nachricht nicht konsumieren. Wenn bei einer verteilten Bereitstellung auf mehreren Computern ein Thema identisch ist, wird die Anwendung häufig verwendet . Die Lösung der oben genannten Probleme erfordert dauerhafte Themen und die Verwendung virtueller Themen
Themenpersistenz
Ändern Sie das Broker-Tag activemq.xml im Verzeichnis activemq_home / config, um das Attribut persistent = "true" hinzuzufügen
<!--
The <broker> element is used to configure the ActiveMQ broker.
-->
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" persistent="true" dataDirectory="${activemq.data}">
Activemq verwendet standardmäßig kahaDB für persistente Daten und wird im Verzeichnis acivemq_home / data / kahaDB gespeichert
Die mq config-Klasse ändert die JmsListenerContainerFactory des Themas
@Bean(name = "topicListenerFactory")
public JmsListenerContainerFactory<DefaultMessageListenerContainer> topicListenerFactory(ConnectionFactory activeMQConnectionFactory){
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setPubSubDomain(true);//"true" for the Publish/Subscribe domain
factory.setSubscriptionDurable(true);// Set this to "true" to register a durable subscription,
factory.setClientId("A");
//
factory.setConnectionFactory(activeMQConnectionFactory);
return factory;
}
Die listenerContainerFactory des persistenten Themas muss setSubscriptionDurable (true) setPubSubDomain (true) und die clientId festlegen
Hinweis: Die für verschiedene Ziele erforderliche clientId der listenerContainerFactory muss unterschiedlich sein. Benennen Sie die clientId daher am besten nach dem Geschäftstyp. Dasselbe Ziel in einer verteilten Bereitstellung: Wenn die Client-ID identisch ist, kann die später gestartete Anwendung das Ziel nicht verwenden (wenn die zuvor gestartete Anwendung geschlossen wurde, kann die später gestartete Anwendung das Ziel verwenden). Wenn Sie einen neuen Zielkonsumenten hinzufügen möchten, müssen Sie daher eine neue listenerContainerFactory erstellen, und die clientId ist anders
Virtuelles Thema (Virtuelles Thema)
Das virtuelle Thema wird über die Warteschlange realisiert. Bei der verteilten Bereitstellung wird dasselbe Ziel nicht wiederholt verwendet
Der Name des virtuellen Themas muss mit dem Präfix VirtualTopic. Beginnen (kann geändert werden, indem die Konfiguration von activemq.xml unter activemq_home / conf geändert wird).
Das Ziel des virtuellen Themas muss mit dem Präfix Consumer. *. VirtualTopic. Beginnen (es kann durch Ändern der Konfiguration activemq.xml unter activemq_home / conf geändert werden). * Die Nummer entspricht der Gruppierung
Beispiel: Wenn der Warteschlangenname VirtualTopic.Orders lautet, lautet das Ziel Consumer.A.VirtualTopic.Orders, Consumer.B.VirtualTopic.Orders in einer verteilten Bereitstellung. Consumer.A.VirtualTopic.Orders wird nur einmal verwendet, wenn Consumer.B. VirtualTopic. Bestellungen werden nur einmal verbraucht
mq config wird wie folgt hinzugefügt
private static final String VIRTUAL_TOPIC_NAME = "VirtualTopic.Orders";
@Bean("virtualTopicQueue")
public ActiveMQTopic virtualTopicQueue(){
return new ActiveMQTopic(VIRTUAL_TOPIC_NAME);
}
veröffentlichen geändert wie folgt
package com.wl.dubbo.blog.mq;
import org.apache.activemq.command.ActiveMQTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;
import javax.jms.Queue;
/**
* Created by wl on 2017/12/28.
*/
@Component
public class ActiveMQSendService {
private static final Logger logger = LoggerFactory.getLogger(ActiveMQSendService.class);
private JmsMessagingTemplate jmsMessagingTemplate;
private Queue queueQueue;
private ActiveMQTopic topicQueue;
private ActiveMQTopic virtualTopicQueue;
@Autowired
public ActiveMQSendService(JmsMessagingTemplate jmsMessagingTemplate,
Queue queueQueue,
ActiveMQTopic topicQueue,
ActiveMQTopic virtualTopicQueue){
this.jmsMessagingTemplate = jmsMessagingTemplate;
this.queueQueue = queueQueue;
this.topicQueue = topicQueue;
this.virtualTopicQueue = virtualTopicQueue;
}
public void sendQueueMessage(String message){
logger.info("send queue:{}",message);
jmsMessagingTemplate.convertAndSend(queueQueue,message);
}
public void sendTopicMessage(String message){
logger.info("send topic:{}",message);
jmsMessagingTemplate.convertAndSend(topicQueue,message);
}
public void sendVirtualTopicQueue(String message){
logger.info("send virtualTopic:{}",message);
jmsMessagingTemplate.convertAndSend(virtualTopicQueue,message);
}
}
Consumer fügt den Listener VirtualTopic.Orders hinzu
@JmsListener(destination = "Consumer.B.VirtualTopic.Orders",containerFactory = "queueListenerFactory" )
public void receiveTopicVirtualQueue(String receiveStr) throws JMSException {
logger.info("=======================Consumer.B.VirtualTopic.topic:{}",receiveStr);
}
Beachten Sie, dass die verwendete containerFactory queueListenerFactory ist (im Gegensatz zum Thema können verschiedene Warteschlangen dieselbe containerFactory verwenden).
Prüfung
@Test
public void testSendVirtualTopic(){
activeMQSendService.sendVirtualTopicQueue("virtualTopic==============");
}
Ergebnis
2018-08-28 00:18:18,814 INFO (DefaultLifecycleProcessor.java:343)- Starting beans in phase 2147483647
2018-08-28 00:18:19,228 INFO (StartupInfoLogger.java:57)- Started ApplicationTest in 6.17 seconds (JVM running for 7.442)
2018-08-28 00:18:19,291 INFO (ActiveMQSendService.java:50)- send virtualTopic:virtualTopic==============
2018-08-28 00:18:22,280 INFO (ReceiverService.java:31)- =======================Consumer.B.VirtualTopic.topic:virtualTopic==============