ssm环境下使用rabbitmq

一、生产者和消费者

rabbitmq是一款消息中间件,最主要的就是消息的生产和消息的消费。原理就是生产者将消息发送到队列中,消费者监听队列,一有消息就立马进行消费。
生产者和消费者类,分别如下:

1、生产者类

package com.selftest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * <p>mq发送消息</p>
 * <p>属性通过spring属性注入的方式注入到ioc容器中</p>
 */
public class GmsMqSender {
    private final Logger logger = LoggerFactory.getLogger(GmsMqSender.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;
    /**
     * 交换机
     */
    private String exchangeName;
    /**
     * 路由键
     */
    private String routingKey;

    public void sendMessage(String msg) {
        try {
            logger.info("发送信息开始");
            // 发送信息 queueName交换机,就是上面的routingKey msg.getSource() 为 test_key
            rabbitTemplate.convertAndSend(exchangeName, routingKey, msg);
            logger.info("发送信息结束,发送的消息:{}", msg);
        } catch (Exception e) {
            logger.error("测试消息发送失败:", e);
        }
    }

    public void setExchangeName(String exchangeName) {
        this.exchangeName = exchangeName;
    }

    public void setRoutingKey(String routingKey) {
        this.routingKey = routingKey;
    }

    public void setRabbitTemplate(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }
}

2、消费者类

package com.selftest;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;

/**
 * <p>mq监听消息,并对消息进行业务处理</p>
 */
@Service("gmsMessageListener")
public class GmsMessageListener implements MessageListener {
    private static final Logger logger = LoggerFactory.getLogger(GmsMessageListener.class);

    /**
     * 消息消费者,只要监听到消息就进行消费处理
     *
     * @param message 监听到的消息
     */
    @Override
    public void onMessage(Message message) {
        logger.info("接收的消息参数:{}", JSON.toJSONString(message));

        try {
            // 对监听到的消息进行相应的业务处理
            String messageStr = new String(message.getBody(), StandardCharsets.UTF_8);
            logger.info("接收到的消息:{}", messageStr);
        } catch (Exception e) {
            logger.error("接收消息出现其他异常: ", e);
        }
    }
}

二、rabbitmq的xml配置

1、消费者配置:

(1)连接rabbitmq服务器,因此需要ip地址,端口,用户名和密码;

(2)声明队列名称;

(3)声明交换机以及交换机类型,将队列与交换机通过路由键绑定起来;

(4)声明消费者,消费者监听队列,将监听方法绑定到队列中,一旦队列中有消息,消费者就进行消费。

2、生产者配置:

生产者与消费者前3步配置都是一样的操作,不同的是需要配置生产者类,将交换机、路由键、以及rabbitTemplate注入到生产者类中。

通常可以将生产者和消费者配置在一个xml文件中,这样方便管理。rabbitmq配置如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <description>rabbitmq消息中间件相关配置</description>
    <!-- 把数据库相关配置信息引入 -->
    <context:property-placeholder location="classpath*:/properties/app.properties"/>
    <!-- 公共部分 -->
    <!-- 创建连接类 连接安装好的 rabbitmq -->
    <!--或者这样配置,connection-factory元素实际就是注册一个org.springframework.amqp.rabbit.connection.CachingConnectionFactory实例 -->
    <rabbit:connection-factory id="connectionFactory" host="${gms.mq.host}" port="${gms.mq.port}"
                               username="${gms.mq.user}" password="${gms.mq.password}"/>
    <rabbit:admin connection-factory="connectionFactory"/>

    <rabbit:queue name="${gms.mq.queueName}" id="queue_1" durable="true" auto-delete="false" exclusive="false"/>

    <!--绑定队列,rabbitmq的exchangeType常用的三种模式:direct,fanout,topic三种,我们用direct模式,即rabbit:direct-exchange标签,Direct交换器很简单,如果是Direct类型,就会将消息中的RoutingKey与该Exchange关联的所有Binding中的BindingKey进行比较,如果相等,则发送到该Binding对应的Queue中。有一个需要注意的地方:如果找不到指定的exchange,就会报错。但routing 
        key找不到的话,不会报错,这条消息会直接丢失,所以此处要小心,auto-delete:自动删除,如果为Yes,则该交换机所有队列queue删除后,自动删除交换机,默认为false -->
    <rabbit:direct-exchange id="exchange_1" name="${gms.mq.exchangeName}" durable="true" auto-delete="false">
        <rabbit:bindings>
            <rabbit:binding queue="queue_1" key="${gms.mq.routingKey}"/>
        </rabbit:bindings>
    </rabbit:direct-exchange>

    <!-- 生产者部分 -->
    <!-- 发送消息的producer类,也就是生产者 -->
    <bean id="msgProducer" class="com.wxl.gms.service.selftest.GmsMqSender">
        <!-- value中的值就是producer中的的routingKey,也就是队列名称,它与上面的rabbit:bindings标签中的key必须相同 -->
        <property name="exchangeName" value="${gms.mq.exchangeName}"/>
        <property name="routingKey" value="${gms.mq.routingKey}"/>
        <property name="rabbitTemplate" ref="rabbitTemplate"/>
    </bean>

    <!-- 消息体序列化,可以自己用fastjson做,JSON.toJSONString(msg) -->
    <rabbit:template exchange="${gms.mq.exchangeName}" id="rabbitTemplate" connection-factory="connectionFactory"/>

    <!-- 消费者部分 自定义接口类 -->
    <bean id="messageListener" class="com.wxl.gms.service.selftest.GmsMessageListener"/>

    <rabbit:listener-container connection-factory="connectionFactory" acknowledge="auto" concurrency="2" prefetch="50">
        <!-- concurrency是消费者个数,prefetch是每个消费者缓存到客户端队列的个数 -->
        <rabbit:listener queue-names="${gms.mq.queueName}" ref="messageListener" method="onMessage"/>
    </rabbit:listener-container>
</beans>

里面的配置信息通常配置在外部,这样方便修改,只需要在xml配置文件中引入即可。

三、总结

只要消息被消费了其他的消费者就没法消费了。例如:有两条消息,如果只有一个消费者,那他将会顺序消费者两条消息,如果有两个消费者,则一人消费一个消息。如果只有一条消息,但有两个消费者,则这条消息只能被其中一个消费者消费,谁来消费这条消息,取决于配置文件消费者的配置顺序。

posted @ 2020-11-06 11:59  jason小蜗牛  阅读(759)  评论(0编辑  收藏  举报