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 install the latest version of the official website server
1.2 rabbitMQ start service management

rabbitMQ start start
1.3 spring pom configuration

<spring-rabbit.version>1.3.9.RELEASE</spring-rabbit.version>
<!-- message queue 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>


1.4   spring config配置

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

配置如下:

<?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, at this time, 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>





public void orderBuilder(int type,String orderCode) {
    String key = "tps."+orderCode;
    orderCode = type+"."+orderCode;
    amqpMaster.convertAndSend(key, orderCode);
    logger.info("The order is added to the message queue, the order Code: {}", key);
}

1.7 Consumer

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

附加类Gson2JsonMessageConverter实现如下,

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 ttl is set, the next modification time, An error will be reported. 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.



Guess you like

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