RabbitMQ spring usage summary

RabbitMQ related concepts are beyond the scope of this article, and the rabbitMQ official website and other blogs have a lot of introductions.

The focus of this article is the construction of spring and rabbit environment and the summary of precautions in use.

1.1 RabbitMQ server construction

Download and install the latest version of the official website server

1.2 rabbitMQ opens service management

rabbitMQ start start

1.3 spring pom configuration

<spring-rabbit.version>1.3.9.RELEASE</spring-rabbit.version>
<!-- 消息队列 rabbitmq -->
<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>${rabbitmq-client.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
    <version>${spring-rabbit.version}</version>
</dependency>

1.4 spring config configuration

在D:\workspace\sps\src\main\resources\spring-rabbitmq.xml

The configuration is as follows:

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

    <mvc:annotation-driven />


    <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.master.ip}" port="${rabbitmq.master.port}" username="${rabbitmq.master.username}" password="${rabbitmq.master.password}" />

    <rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
                     exchange="order_topic_exchange" message-converter="gsonConverter" />

    <rabbit:admin connection-factory="connectionFactory" />

    <rabbit:queue name="orderQueue" durable="true"  />
    <rabbit:queue name="orderPayQueryQueue" durable="true" auto-delete="false" exclusive="false">
        <rabbit:queue-arguments>
            <entry key="x-message-ttl">
                <value  type="java.lang.Long">600000</value>
            </entry>
            <entry key="x-dead-letter-exchange" value="pay_delay_exchange"/>
        </rabbit:queue-arguments>
    </rabbit:queue>

    <rabbit:queue name="orderPayDelayQueryQueue" durable="true"/>

    <rabbit:topic-exchange name="pay_delay_exchange">
        <rabbit:bindings>
            <rabbit:binding queue="orderPayDelayQueryQueue" pattern="orderPay.#"/>
        </rabbit:bindings>
    </rabbit:topic-exchange>
    <rabbit:topic-exchange name="order_topic_exchange">
        <rabbit:bindings>
            <rabbit:binding queue="orderQueue" pattern="sps.#"/>
            <rabbit:binding queue="orderPayQueryQueue" pattern="orderPay.#"/>
        </rabbit:bindings>
    </rabbit:topic-exchange>

    <rabbit:listener-container connection-factory="connectionFactory" acknowledge="manual"  concurrency="10">
        <rabbit:listener queues="orderQueue" ref="orderQueueListener"/>

    </rabbit:listener-container>
   
    <bean id="orderQueueListener" class="com.supuy.sps.services.queue.OrderQueueListener" />

    <bean id="gsonConverter" class="com.supuy.core.mq.Gson2JsonMessageConverter"/>


</beans>

1.5 Delayed message queue

Sometimes, for various reasons, we want to achieve the purpose of delayed consumption, but rabbitMQ does not provide this function. In this case, it can be achieved through x-message-ttl and x-dead-letter-exchange .

    <rabbit:queue name="orderPayQueryQueue" durable="true" auto-delete="false" exclusive="false">
        <rabbit:queue-arguments>
            <entry key="x-message-ttl">
                <value  type="java.lang.Long">600000</value>
            </entry>
            <entry key="x-dead-letter-exchange" value="pay_delay_exchange"/>
        </rabbit:queue-arguments>
    </rabbit:queue>

1.6 Producers

@Override
public void orderBuilder(int type,String orderCode) {
    String key = "tps."+orderCode;
    orderCode = type+"."+orderCode;
    amqpMaster.convertAndSend(key, orderCode);
    logger.info("订单加入消息队列,订单编码:{}", key);
}

1.7 Consumers

package com.supuy.tps.service.queue;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import com.supuy.tps.common.mq.Gson2JsonMessageConverter;
import com.supuy.tps.dto.bean.WmsOrderParam;
import com.supuy.tps.service.IOrderShopService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Created by bill on 2016/5/31.
 */
public class OrderSendQueueListener implements ChannelAwareMessageListener {
    private static Logger logger = LoggerFactory.getLogger(OrderSendQueueListener.class);
    @Autowired
    private Gson2JsonMessageConverter messageConverter;
    @Autowired
    private IOrderShopService orderShopService;
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        channel.basicQos(100);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        String data=(String)messageConverter.fromMessage(message);
        if (data!=null){
            WmsOrderParam wmsOrderParam= JSON.parseObject(data,WmsOrderParam.class);
            if (wmsOrderParam != null){
                wmsOrderParam.setOrderCode(wmsOrderParam.getOrderCode().substring(1));
                orderShopService.pushOrderLogInfo(wmsOrderParam);
            }
        }
    }
}

The additional class Gson2JsonMessageConverter is implemented as follows,

package com.supuy.tps.common.mq;

import com.google.gson.Gson;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.support.converter.AbstractJsonMessageConverter;
import org.springframework.amqp.support.converter.ClassMapper;
import org.springframework.amqp.support.converter.DefaultClassMapper;
import org.springframework.amqp.support.converter.MessageConversionException;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class Gson2JsonMessageConverter extends AbstractJsonMessageConverter {
      
    private static Log log = LogFactory.getLog(Gson2JsonMessageConverter.class);
      
    private static ClassMapper classMapper =  new DefaultClassMapper();
  
    private static Gson gson = new Gson();
  
    public Gson2JsonMessageConverter() {  
        super();  
    }  


    @Override  
    protected Message createMessage(Object object,
            MessageProperties messageProperties) {
        byte[] bytes = null;  
        try {  
            String jsonString = gson.toJson(object);  
            bytes = jsonString.getBytes(getDefaultCharset());  
        }  
        catch (IOException e) {  
            throw new MessageConversionException(
                    "Failed to convert Message content", e);  
        }  
        messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
        messageProperties.setContentEncoding(getDefaultCharset());  
        if (bytes != null) {  
            messageProperties.setContentLength(bytes.length);  
        }  
        classMapper.fromClass(object.getClass(), messageProperties);
        return new Message(bytes, messageProperties);
    }  
  
    @Override  
    public Object fromMessage(Message message)
            throws MessageConversionException {
        Object content = null;  
        MessageProperties properties = message.getMessageProperties();
        if (properties != null) {  
            String contentType = properties.getContentType();  
            if (contentType != null && contentType.contains("json")) {  
                String encoding = properties.getContentEncoding();  
                if (encoding == null) {  
                    encoding = getDefaultCharset();  
                }  
                try {  
                        Class<?> targetClass = getClassMapper().toClass(
                                message.getMessageProperties());
                        content = convertBytesToObject(message.getBody(),  
                                encoding, targetClass);  
                }  
                catch (IOException e) {  
                    throw new MessageConversionException(
                            "Failed to convert Message content", e);  
                }  
            }  
            else {  
                log.warn("Could not convert incoming message with content-type ["  
                        + contentType + "]");  
            }  
        }  
        if (content == null) {  
            content = message.getBody();  
        }  
        return content;  
    }  
  
    private Object convertBytesToObject(byte[] body, String encoding,  
            Class<?> clazz) throws UnsupportedEncodingException {  
        String contentAsString = new String(body, encoding);  
        return gson.fromJson(contentAsString, clazz);  
    }

    @Override
    public ClassMapper getClassMapper() {
        return new DefaultClassMapper();

    }
}  

1.8   Q&A

1 After the ttl is set, an error will be reported next time the time is modified. At this time, you need to delete the queue and restart the project.

2 After receiving the message, if an error occurs, the message will be continuously occupied and cannot be consumed. Therefore, use the ack, nack, and reject of the message.

{{o.name}}
{{m.name}}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324077287&siteId=291194637