spring注解编写rabbitmq轮询代码各种坑

1.生产者代码 

package com.cloudtech.web.mq.config;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;

/**
 *  日志管理的Rabbit配置类的具体实现类
* @ClassName: LogRabbitConfiguration  
* @Description:   
* @author wude  
* @date 2018年8月13日  
*
 */
@Configuration
@PropertySource(value={"classpath:rabbit.properties"})
public class LogRabbitConfiguration extends AbstractRabbitConfiguration {
	
	/** 质控模块分钟队列名称  */
    private String qaQueueName;
	 
   
    @Bean(name="qaMinuteQueue")
    public Queue qaMinuteQueue() {
    	//声明队列  说明队列存在则什么都不做  如果不存在则自动创建
		//参数1.队列名称
		//参数2 是否持久化队列,我们中的队列模式是指内存中的,如果rabbit重启会丢失,如果我们设置为true,则会保存到el-lang自带的数据库中重启后,会重新读取
		//参数3 是否排外,有两个作用,当我们连接关闭后,是否自动关闭队列,作用二 是否私用当天的队列,如果私有了,则其他队列不允许访问,如果为true,一般只适用于一个消费者的时候
		//参数4 是否自动删除
        return new Queue(qaQueueName,true);
    }
    
    @Bean(name="qaMinuteTemplate")
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate qaMinuteTemplate() {
        RabbitTemplate template = new RabbitTemplate(rabbit_connectionFactory());
        //对象格式
        template.setMessageConverter(jsonMessageConverter());
        //template.setExchange("");
        //template.setQueue(qaQueueName);
        return template;
    }
}

发送接口 

package com.cloudtech.web.service;

import com.cloudtech.web.entity.StationDetailInfo;
import com.cloudtech.web.vo.SecondDetailTempVo;

/**
 * 
* @ClassName: RabbitSend  
* @Description:   定义一个泛型接口,用于发送消息,T为要发送的消息类型
* @author wude  
* @date 2018年8月23日  
*  
* @param 
 */
public interface RabbitSend {
	/** 发送秒级数据  入库保存文件 */
    public void sendQaMinute(StationDetailInfo detail);
}
package com.cloudtech.web.service.impl;

import javax.annotation.Resource;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

import com.cloudtech.web.entity.MessageDetails;
import com.cloudtech.web.service.RabbitSend;
import com.cloudtech.web.vo.SecondDetailTempVo;

/**
 * 用于发送日志消息的通用实现类
 * 
 * @author wude
 *
 */
@Component
public class LogRabbitSend implements RabbitSend {
	 @Resource(name = "qaMinuteQueue")
	 private Queue qaMinuteQueue;


	@Override
	public void sendQaMinute(MessageDetails detail) {
		qaMinuteTemplate.convertAndSend(qaMinuteQueue.getName(),detail);		
	}
}

注意:qaMinuteTemplate.convertAndSend(qaMinuteQueue.getName(),detail);    

重点就是这句代码,第一个参数一定要设置队列,在config中配置无效,我研究了很久才发现需要设置这个参数

2.消费者

package com.cloudtech.web.mq.config;

import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * 
* @ClassName: AbstractRabbitConfiguration  
* @Description:   抽象类,rabbitMQ的主配置类
* @author wude  
* @date 2018年8月13日  
*
 */
@Configuration
@PropertySource(value={"classpath:rabbit.properties"})
public abstract class AbstractRabbitConfiguration {
	@Value("${rabbit.host}")
    private String host;
	
	@Value("${rabbit.port}")
    private Integer port;
	
	@Value("${rabbit.username}")
    private String username;
	
	@Value("${rabbit.password}")
    private String password;
	
	@Value("${rabbit.virtual}")
    private String virtual;

    protected abstract void configureRabbitTemplate(RabbitTemplate template);

    /**
     * 由于connectionFactory会与项目中的redis的connectionFactory命名冲突,
     * 所以这边改名为rabbit_connectionFactory
     * 
     * @return
     */
    @Bean
    public ConnectionFactory rabbit_connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(
        		host);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setPort(port);
        connectionFactory.setVirtualHost(virtual);
        return connectionFactory;
    }
    
    

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(rabbit_connectionFactory());
        template.setMessageConverter(jsonMessageConverter());
        configureRabbitTemplate(template);
        return template;
    }

    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public AmqpAdmin amqpAdmin() {
        RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbit_connectionFactory());
        return rabbitAdmin;
    }
}

 

package com.cloudtech.web.mq.config;

import java.util.Set;

import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import com.cloudtech.web.service.impl.RabbitRecServiceImpl;

/**
 *
* @ClassName: LogRabbitConfiguration  
* @Description:    日志管理的Rabbit配置类的具体实现类
* @author wude  
* @date 2018年8月13日  
*
 */
@Configuration
@PropertySource(value={"classpath:rabbit.properties"})
public class LogRabbitConfiguration extends AbstractRabbitConfiguration {
	@Autowired
	private RabbitRecServiceImpl rabbitRecServiceImpl;
	
	@Value("${queueName}")
    private String queueName;
	
	@Bean(name="qaMinuteQueue")
    public Queue qaMinuteQueue() {
    	//声明队列  说明队列存在则什么都不做  如果不存在则自动创建
		//参数1.队列名称
		//参数2 是否持久化队列,我们中的队列模式是指内存中的,如果rabbit重启会丢失,如果我们设置为true,则会保存到el-lang自带的数据库中重启后,会重新读取
		//参数3 是否排外,有两个作用,当我们连接关闭后,是否自动关闭队列,作用二 是否私用当天的队列,如果私有了,则其他队列不允许访问,如果为true,一般只适用于一个消费者的时候
		//参数4 是否自动删除
        return new Queue(queueName,true);
    }
	
	
 /**
     * 设置Exchange为LOG_EXCHANGE_NAME,RoutingKey为LOG_ROUTING_KEY,这样将信息发送到
     * Exchange为LOG_EXCHANGE_NAME,RouteKey为LOG_ROUTING_KEY的通道中
     */
    @Override
    protected void configureRabbitTemplate(RabbitTemplate template) {
        template.setQueue(queueName);
    }
    
    
    

    
    /**
     * 这个bean用于监听服务端发过来的消息,监听的Queue为logQueue(),
     * 因为该Queue绑定了logExchange和logRouteKey, 所以它可以接收到我们发送的日志消息
     * @return
     */
    @Bean
    public SimpleMessageListenerContainer messageListenerContainer() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(
                rabbit_connectionFactory());
        container.setConcurrentConsumers(5);
        container.setQueueNames(queueName);
        container.setPrefetchCount(1);  //告诉服务器,在我没有确定当前消息完成之前,不要给我发新的消息
        container.setMessageListener(rabbitRecServiceImpl);
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        return container;
    }
}

接收消息的代码

package com.cloudtech.web.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

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;
import org.springframework.stereotype.Component;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.cloudtech.web.cache.FieldConfigCache;
import com.cloudtech.web.cache.RuleCodeCache;
import com.cloudtech.web.cache.SystemConfigCache;
import com.cloudtech.web.dao.StationDetailInfoMapper;
import com.cloudtech.web.dao.StationInfoMapper;
import com.cloudtech.web.dao.StationQualityMapper;
import com.cloudtech.web.dao.WarnNoticeInfoMapper;
import com.cloudtech.web.entity.FieldConfig;
import com.cloudtech.web.entity.RuleCode;
import com.cloudtech.web.entity.StationDetailInfo;
import com.cloudtech.web.entity.StationInfo;
import com.cloudtech.web.entity.StationQualityDetailInfo;
import com.cloudtech.web.entity.WarnNoticeInfo;
import com.cloudtech.web.enums.FieldTypeCode;
import com.cloudtech.web.enums.IsLand;
import com.cloudtech.web.enums.WarnLevel;
import com.cloudtech.web.enums.WarnType;
import com.cloudtech.web.util.Constans;
import com.cloudtech.web.util.ConvertUtils;
import com.cloudtech.web.util.JacksonUtil;
import com.cloudtech.web.util.ReflectUtil;
import com.cloudtech.web.util.TimeUtils;
import com.rabbitmq.client.Channel;
@Component
public class RabbitRecServiceImpl implements  ChannelAwareMessageListener{
	private static Logger logger = LoggerFactory.getLogger(RabbitRecServiceImpl.class);

	
	public void onMessage(Message message, Channel channel) throws Exception {
		 try {
				basicACK(message, channel);
			} catch (IOException e) {
				basicNACK(message, channel);
			}
	}

	
	 //正常消费掉后通知mq服务器移除此条mq
    @SuppressWarnings("unused")
	private void basicACK(Message message,Channel channel){
        try{                           
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        }catch(IOException e){
        	logger.debug("通知服务器移除mq时异常,异常信息:"+e);
        }
    }
    //处理异常,mq重回队列
    @SuppressWarnings("unused")
	private void basicNACK(Message message,Channel channel){
        try{
            channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
        }catch(IOException e){
        	logger.debug("mq重新进入服务器时出现异常,异常信息:"+e);
        }
    }
}

 

你可能感兴趣的:(#,rabbitMQ消息中间件)