springboot integra la persistencia activemq y tpoic y el tema virtual (tema virtual)

mq se divide en cola (modo de cola, el productor produce un mensaje, que solo puede ser consumido por un consumidor) tema (modo de publicación / suscripción, el productor produce un mensaje, que puede ser consumido por varios consumidores)

configuración de 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

clase de configuración mq

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);
    }


}

publicar 

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);
    }

}

consumidor

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);

    }

  


}

Comenzar la clase

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");
    }
}

Clase de prueba

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================");
    }

}

El mensaje del tema anterior no es persistente. Si el mensaje del tema se envía antes de que se inicie la aplicación de consumo, el consumidor no puede consumir el mensaje; y si en el caso de la implementación distribuida de múltiples máquinas, un tema será el mismo La aplicación consume muchas . Resolver los problemas anteriores requiere temas persistentes y el uso de temas virtuales.

persistencia del tema

Modifique la etiqueta de agente activemq.xml en el directorio activemq_home / config para agregar el atributo persistent = "true"

 <!--
        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 utiliza kahaDB para datos persistentes de forma predeterminada y se almacena en el directorio acivemq_home / data / kahaDB

La clase mq config modifica JmsListenerContainerFactory del tema

@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;

    }

El listenerContainerFactory del tema persistente debe establecer setSubscriptionDurable (true) setPubSubDomain (true) y establecer el clientId

Nota: El clientId de listenerContainerFactory requerido por diferentes destinos debe ser diferente, por lo que es mejor nombrar el clientId de acuerdo con el tipo de negocio. El mismo destino en una implementación distribuida, si el clientId es el mismo, la aplicación iniciada más tarde no puede consumir el destino (si la aplicación iniciada antes se cierra, la aplicación iniciada más tarde puede consumir el destino). Por lo tanto, si desea agregar un nuevo consumidor de destino, debe crear un nuevo listenerContainerFactory, y el clientId es diferente

Tema virtual (tema virtual)

El tema virtual se realiza a través de la cola. En la implementación distribuida, el mismo destino no se consumirá repetidamente

El nombre del tema virtual debe comenzar con el prefijo VirtualTopic. (Se puede modificar cambiando la configuración de activemq.xml en activemq_home / conf)

El destino del tema virtual debe comenzar con el prefijo Consumer. *. VirtualTopic. (Se puede modificar cambiando la configuración activemq.xml en activemq_home / conf) * El número es equivalente a agrupar

Ej .: Si el nombre de la cola es VirtualTopic.Orders, el destino es Consumer.A.VirtualTopic.Orders, Consumer.B.VirtualTopic.Orders en una implementación distribuida, Consumer.A.VirtualTopic.Orders solo se consumirán una vez Consumer.B. VirtualTopic. Los pedidos solo se consumirán una vez

mq config se agrega de la siguiente manera

private static final String VIRTUAL_TOPIC_NAME = "VirtualTopic.Orders";


    @Bean("virtualTopicQueue")
    public ActiveMQTopic virtualTopicQueue(){
        return new ActiveMQTopic(VIRTUAL_TOPIC_NAME);
    }

publicar enmendado de la siguiente manera

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);
    }


}

El consumidor agrega el oyente VirtualTopic.Orders

@JmsListener(destination = "Consumer.B.VirtualTopic.Orders",containerFactory = "queueListenerFactory" )
    public void receiveTopicVirtualQueue(String receiveStr) throws JMSException {
        logger.info("=======================Consumer.B.VirtualTopic.topic:{}",receiveStr);

    }

Tenga en cuenta que el containerFactory usado es queueListenerFactory (al contrario del tema, diferentes colas pueden usar el mismo containerFactory)

prueba

@Test
    public void testSendVirtualTopic(){
        activeMQSendService.sendVirtualTopicQueue("virtualTopic==============");
    }

resultado

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==============

 

Supongo que te gusta

Origin blog.csdn.net/name_is_wl/article/details/82120329
Recomendado
Clasificación