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中配置无效,我研究了很久才发现需要设置这个参数
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);
}
}
}