springmvc集成activemq和springboot集成rabbitmq

 

因为最近开发了一个后台系统中有推送消息的功能,最开始的做法是在后台系统一个表单页面填写推送信息,渠道等,点击提交完成推送。

单人或者单渠道推送的时候后台系统直接完成推送,返回成功到页面。后来渠道增加或者接受人从单个对象变成集合的时候系统就出问题了,页面会一直卡在程序运行后才会跳转。

由于赶进度且只是为了完成需求,当时就直接new了一个线程去完成推送,主方法不用等结果直接返回成功,然后线程完成推送后去做异步处理。后来没事干的时候想起来这一块觉得添加一个序列比较合适,就有了接下来的记录。

关于activemq、rabbitmq、kafka区别和介绍请阅读

https://blog.csdn.net/lifaming15/article/details/79942793

一:springmvc集成activemq

本人框架是基于maven的springMVC框架

1:添加jar包

 

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-all</artifactId>
    <version>5.11.0</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jms</artifactId>
    <version>4.0.8.RELEASE</version>
</dependency>

 

这里的spring-jms的版本一定要和系统中spring的版本一致,刚开始没有注意到这个问题,是直接看jar包拷贝的maven依赖,后来系统启动一致报什么注入失败的问题,找了好久才知道是版本冲突。

2:添加spring配置文件spring-context-jms.xml

 

<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
   <property name="brokerURL" value="${activemq.host}" />
</bean>

<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
   <property name="connectionFactory" ref="targetConnectionFactory" />
   <property name="maxConnections" value="10" />
</bean>

<bean id="connectionFactory"
   class="org.springframework.jms.connection.SingleConnectionFactory">
   <property name="targetConnectionFactory" ref="pooledConnectionFactory" />
</bean>

<!--这个是队列目的地,点对点的 -->
<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
   <constructor-arg>
      <value>queue1</value>
   </constructor-arg>
</bean>
<!--这个是主题目的地,一对多的
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
   <constructor-arg value="topic" />
</bean>
-->
<!-- 定义监听消息队列(Queue),queue2-->
<bean id="messageQueueDestination" class="org.apache.activemq.command.ActiveMQQueue">
   <!-- 设置消息队列的名字 -->
   <constructor-arg>
      <value>queue2</value>
   </constructor-arg>
</bean>
<!-- 配置消息队列监听者(Queue),代码下面给出,只有一个onMessage方法 -->
<bean id="queueMessageListener" class="com.jeeplus.modules.jms.listener.QueueMessageListener" />

<!-- 消息监听容器(Queue),配置连接工厂,监听的队列是queue2,监听器是上面定义的监听器 ,系统里直接使用监听 -->
<bean id="jmsContainer"
     class="org.springframework.jms.listener.DefaultMessageListenerContainer">
   <property name="connectionFactory" ref="connectionFactory" />
   <property name="destination" ref="messageQueueDestination" />
   <property name="messageListener" ref="queueMessageListener" />
</bean>


<!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
   <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
   <property name="connectionFactory" ref="connectionFactory" />
   <!-- 消息转换器
      <property name="messageConverter" ref="objConverter"/>
       -->
   <property name="defaultDestination" ref="queueDestination" />
   <property name="receiveTimeout" value="10000" />
</bean>


<!-- 类型转换器
<bean id="objConverter" class="com.jeeplus.modules.jms.converter.ObjectConverter"/>
   -->

<!--queue消息生产者 -->
<bean id="producterService" class="com.jeeplus.modules.jms.service.ProducterService">
   <property name="jmsTemplate" ref="jmsTemplate"></property>
</bean>

<!--queue消息消费者 -->
<bean id="consumerService" class="com.jeeplus.modules.jms.service.ConsumerService">
   <property name="jmsTemplate" ref="jmsTemplate"></property>
</bean>

 

 

 

上边注释写的其实已经很详细了。配置连接,定义序列,配置spring工具,配置监听,大概就可以了。

3:java代码实现

首先在系统中其实用到的没有消费者,因为我的消费者其实就是监听,处理逻辑在监听中实现了。vo文件夹可以自定义object类型。

监听QueueMessageListener:

 

package com.jeeplus.modules.jms.listener;


import com.jeeplus.modules.sms.common.utils.PushMsgUtil;
import com.jeeplus.modules.sms.sendmessage.entity.MessageSend;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jms.*;

public class QueueMessageListener implements MessageListener {

    protected Logger logger = LoggerFactory.getLogger(getClass());
    //当收到消息时,自动调用该方法。
    public void onMessage(Message message) {
        MessageSend tm = new MessageSend();
        if (message instanceof ObjectMessage) {
            ObjectMessage objectMessage = (ObjectMessage) message;
            try {
                tm = (MessageSend) objectMessage.getObject();
                System.out.println("ConsumerMessageListener收到了自定义消息:\t"
                        + tm);
                logger.info("ConsumerMessageListener收到了自定义消息:\t"
                        + tm);
                PushMsgUtil.pushMsg(tm);
            } catch (JMSException e) {
                e.printStackTrace();
            }

        }
        if (message instanceof TextMessage) {
            TextMessage tx = (TextMessage) message;
            try {
                System.out.println("ConsumerMessageListener收到了文本消息:\t"
                        + tx.getText());

                logger.info("ConsumerMessageListener收到了文本消息:\t"
                        + tx.getText());
            } catch (JMSException e) {
                e.printStackTrace();
            }

        }

    }
}

 

 

 

生产者ProducterService:

 

package com.jeeplus.modules.jms.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import java.io.Serializable;

/**
 * Created by huiyunfei on 2017/7/20.
 */
public class ProducterService {

    protected Logger logger = LoggerFactory.getLogger(getClass());
    private JmsTemplate jmsTemplate;

    /**
     * 向指定队列发送消息
     */
    public void sendMessage(Destination destination, final String msg) {
        System.out.println("向队列" + destination.toString() + "发送了消息------------" + msg);
        jmsTemplate.send(destination, new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                return session.createTextMessage(msg);
            }
        });
    }

    /**
     * 向默认队列发送消息
     */
    public void sendMessage(final String msg) {
        String destination =  jmsTemplate.getDefaultDestination().toString();
        System.out.println("向队列" +destination+ "发送了消息------------" + msg);
        jmsTemplate.send(new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                return session.createTextMessage(msg);
            }
        });

    }

    /**
     * 向指定队列发送自定义消息
     */
    public void sendMessage(Destination destination, final Object msg) {
        System.out.println("向队列" + destination.toString() + "发送了消息------------" + msg);
        jmsTemplate.send(destination, new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                return session.createObjectMessage((Serializable) msg);
                //return session.createTextMessage(ObjectConverter.class.);
            }
        });
    }

    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

}




 

 

 

消费者:

 

package com.jeeplus.modules.jms.service;

import org.springframework.jms.core.JmsTemplate;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.TextMessage;

/**
 * Created by huiyunfei on 2017/7/20.
 */
public class ConsumerService {

    private JmsTemplate jmsTemplate;

    /**
     * 接受消息
     */
    public void receive(Destination destination) {
        TextMessage tm = (TextMessage) jmsTemplate.receive(destination);
        try {
            System.out.println("从队列" + destination.toString() + "收到了消息:\t"
                    + tm.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }


}





 

 

 

4:测试类

 

 

package com.jeeplus.modules.jms;

import com.jeeplus.modules.jms.service.ConsumerService;
import com.jeeplus.modules.jms.service.ProducterService;
import com.jeeplus.modules.jms.vo.TestMessage;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import javax.jms.Destination;

/**
 * Created by huiyunfei on 2017/7/20.
 */
/**
 * @Description: activemq消息队列测试
 * @Author:huiyunfei
 * @Date: 2017/7/21
 */
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {
        "classpath:spring-context.xml"})
public class SpringJmsTest {

    /**
     * 队列名queue1
     */
    @Autowired
    private Destination queueDestination;

    /**
     * 队列名queue2
     */
    @Autowired
    private Destination messageQueueDestination;

    /**
     * 队列消息生产者
     */
    @Autowired
    @Qualifier("producterService")
    private ProducterService producer;

    /**
     * 队列消息消费者
     */
    @Autowired
    @Qualifier("consumerService")
    private ConsumerService consumer;

    /**
     * 测试生产者向queue1发送消息
     */
    @Test
    public void testProduce() {
        String msg = "Hello world!";
        producer.sendMessage(msg);
    }

    /**
     * 测试消费者从queue1接受消息
     */
    @Test
    public void testConsume() {
        consumer.receive(queueDestination);
    }

    /**
     * 测试消息监听
     *
     * 1.生产者向队列queue2发送消息
     *
     * 2.ConsumerMessageListener监听队列,并消费消息
     */
    @Test
    public void testSend() {
        producer.sendMessage(messageQueueDestination, "Hello China~~~~~~~~~~~~~~~");
    }
    /**
     * 测试自定义消息监听
     *
     * 1.生产者向队列queue2发送消息
     *
     * 2.ConsumerMessageListener监听队列,并消费消息
     */
    @Test
    public void testCustomSend() {
        TestMessage testMessage=new TestMessage();
        testMessage.setId("1");
        testMessage.setUser("yunfei");
        testMessage.setTitle("title");
        testMessage.setContent("----------hello test message----------");
        producer.sendMessage(messageQueueDestination, testMessage);
    }
}







二:springboot集成rabbitmq

配置文件:

  redis:
    host: 127.0.0.1
    password:
    port: 6379
    maxWaitMillis: 10000
    maxTotal: 200
    testOnBorrow: true
    testOnReturn: true
    timeout: 3600
    maxIdle: 200

pom:


        <!-- 添加springboot对amqp的支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

 

rabbitmq三种模式:

       Direct是RabbitMQ默认的交换机模式,也是最简单的模式.即创建消息队列的时候,指定一个BindingKey.当发送者发送消息的时候,指定对应的Key.当Key和消息队列的BindingKey一致的时候,消息将会被发送到该消息队列中.

  topic转发信息主要是依据通配符,队列和交换机的绑定主要是依据一种模式(通配符+字符串),而当发送消息的时候,只有指定的Key和该模式相匹配的时候,消息才会被发送到该消息队列中.

  Fanout是路由广播的形式,将会把消息发给绑定它的全部队列,即便设置了key,也会被忽略.

测试:

配置文件:

#我测试的时候这个配置文件压根就没有添加,也能正常使用,rabbitmq应该是使用了默认的配置,而我刚好就是默认的rabbitmq配置比如端口之类的
spring.application.name=spirng-boot-rabbitmq-sender
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

directconfig类:

package com.example.rabbitmq.direct;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by hui.yunfei@qq.com on 2019/5/20
 * 配置Queue(消息队列).那注意由于采用的是Direct模式,需要在配置Queue的时候,指定一个键,使其和交换机绑定
 */
@Configuration
public class SendConf {
    @Bean
    public Queue queue() {
        return new Queue("hello2");
    }
}




topic配置类:

package com.example.rabbitmq.topic;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by hui.yunfei@qq.com on 2019/5/22
 */
@Configuration
public class SendExchangeConf {
    @Bean(name="message")
    public Queue queueMessage() {
        return new Queue("topic.message");
    }

    @Bean(name="messages")
    public Queue queueMessages() {
        return new Queue("topic.messages");
    }

    @Bean
    public TopicExchange exchange() {
        return new TopicExchange("exchange");
    }

    @Bean
    Binding bindingExchangeMessage(@Qualifier("message") Queue queueMessage, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
    }

    @Bean
    Binding bindingExchangeMessages(@Qualifier("messages") Queue queueMessages, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");//*表示一个词,#表示零个或多个词
    }
}

fanout配置类:

package com.example.rabbitmq.fanout;

import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by hui.yunfei@qq.com on 2019/5/22
 */
@Configuration
public class SendFanoutConf {
    @Bean(name="Amessage")
    public Queue AMessage() {
        return new Queue("fanout.A");
    }


    @Bean(name="Bmessage")
    public Queue BMessage() {
        return new Queue("fanout.B");
    }

    @Bean(name="Cmessage")
    public Queue CMessage() {
        return new Queue("fanout.C");
    }

    @Bean
    FanoutExchange fanoutExchange() {
        return new FanoutExchange("fanoutExchange");//配置广播路由器
    }
//下面代码注释掉也可以接收到消息
//    @Bean
//    Binding bindingExchangeA(@Qualifier("Amessage") Queue AMessage, FanoutExchange fanoutExchange) {
//        return BindingBuilder.bind(AMessage).to(fanoutExchange);
//    }
//
//    @Bean
//    Binding bindingExchangeB(@Qualifier("Bmessage") Queue BMessage, FanoutExchange fanoutExchange) {
//        return BindingBuilder.bind(BMessage).to(fanoutExchange);
//    }
//
//    @Bean
//    Binding bindingExchangeC(@Qualifier("Cmessage") Queue CMessage, FanoutExchange fanoutExchange) {
//        return BindingBuilder.bind(CMessage).to(fanoutExchange);
//    }
}



 

接收类三种模式公用一个:

package com.example.rabbitmq.topic;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * Created by hui.yunfei@qq.com on 2019/5/22
 */
@Component
public class HellowReceive {


    @RabbitListener(queues="hello")    //监听器监听指定的Queue
    public void processC(User obj) {
        System.out.println("Receive hello:"+obj.toString());
    }
    @RabbitListener(queues="hello2")    //监听器监听指定的Queue
    public void processB(User obj) {
        System.out.println("Receive hello2:"+obj.toString());
    }

    @RabbitListener(queues="fanout.A")    //监听器监听指定的Queue
    public void process1(String str) {
        System.out.println("fanout.A:"+str);
    }
    @RabbitListener(queues="fanout.B")    //监听器监听指定的Queue
    public void process2(String str) {
        System.out.println("fanout.B:"+str);
    }


    @RabbitListener(queues="topic.message")    //监听器监听指定的Queue
    public void process1(String str) {
        System.out.println("message:"+str);
    }
    @RabbitListener(queues="topic.messages")    //监听器监听指定的Queue
    public void process2(String str) {
        System.out.println("messages:"+str);
    }
}

发送类三种模式公用一个测试类:

package com.example.rabbitmq.direct;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * Created by hui.yunfei@qq.com on 2019/5/21
 */
@RunWith(SpringRunner.class)
@SpringBootTest(value={"DEPLOY=dev"})
public class HelloSenderTest {
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Test
    public void direct(){
        User user=new User();
        user.setId(1);
        user.setName("yunfei");
        amqpTemplate.convertAndSend("hello2",user);
    }
    @Test
    public void topic(){
        amqpTemplate.convertAndSend("exchange","topic.message","123");
    }
    @Test
    public void fanout(){
        amqpTemplate.convertAndSend("fanoutExchange","","123");
    }

}

 

结果:

非fanout模式都需要指定序列quene的routingkey,direct会发给key一致的序列,topic会发给匹配规则的序列,fanout发送给所有绑定的序列。

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值