java rabbitmq动态注册,监听实现
最近项目中用到rabbitmq,将rabbitmq动态注册、监听、发送消息、接收消息进行封装,方便调用
话不多说,直接上代码
程序员不骗程序员
1.配置类代码
@EnableRabbit
@Configuration
public class RabbitConfig {
private static final Logger logger = LoggerFactory.getLogger(RabbitConfig.class) ;
@Autowired
MqQueueConfigService mqQueueConfigService;
private List<MqQueueConfig> queueConfigList;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private MqMessageHandleListener mqMessageHandleListener;
public static Map<String, List<ReflectVo>> queueMap=new HashMap<>();
@Bean
@ConditionalOnMissingBean
public RabbitConfigInitializer rabbitModuleInitializer(AmqpAdmin amqpAdmin) {
queueConfigList=mqQueueConfigService.selectList();
return new RabbitConfigInitializer(amqpAdmin, queueConfigList);
}
@Bean
public MessageConverter myMessageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate();
rabbitTemplate.setConnectionFactory(connectionFactory);
rabbitTemplate.setMandatory(true);
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
});
rabbitTemplate.setReturnsCallback(returnedMessage -> {
});
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
return rabbitTemplate;
}
@Bean
public SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setDefaultRequeueRejected(false);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.setExposeListenerChannel(true);
List<String> queueNames=getQueueNames() ;
for (String queueName:queueNames) {
container.addQueueNames( queueName);
}
container.setMessageListener(new ChannelAwareMessageListener() {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
String key=message.getMessageProperties().getConsumerQueue()+message.getMessageProperties().getReceivedRoutingKey();
if (!CollectionUtils.isEmpty( queueMap.get(key))){
Gson gson = new Gson();
MqMessage mqMessage = gson.fromJson(msg, MqMessage.class);
try {
mqMessageHandleListener.handleMessage(queueMap.get(key),mqMessage);
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} catch (IOException e) {
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
e.printStackTrace();
}
}
}
});
return container;
}
private List<String> getQueueNames(){
List<String> queueNames=new ArrayList<>();
Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(MqConfigInterface.class);
List<ReflectVo> reflectVoList=null;
ReflectVo reflectVo=null;
for (Object bean : beanMap.values()) {
Class<?> clazz = bean.getClass();
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
if (declaredMethod.isAnnotationPresent(MqConfigMethod.class)) {
MqConfigMethod annotation = declaredMethod.getDeclaredAnnotation(MqConfigMethod.class);
String key=annotation.queues()+annotation.routingKey();
reflectVo=new ReflectVo();
reflectVo.setClassName(clazz.getName());
reflectVo.setQueueName(annotation.queues());
reflectVo.setRoutingKey(annotation.routingKey());
reflectVo.setMethodName(declaredMethod.getName());
queueNames.add(annotation.queues());
if (null !=queueMap&& null!= queueMap.get(key)){
reflectVoList=queueMap.get(key);
reflectVoList.add(reflectVo);
queueMap.put(key,reflectVoList);
}else {
reflectVoList=new ArrayList<>();
reflectVoList.add(reflectVo);
queueMap.put(key,reflectVoList);
}
}
}
}
return queueNames;
}
}
2.监听处理类
@Component
public class MqMessageHandleListener {
private static final Logger logger = LoggerFactory.getLogger(MqMessageHandleListener.class) ;
public void handleMessage(List<ReflectVo> reflectVoList, MqMessage mqMessage) throws Exception{
for (ReflectVo reflectVo:reflectVoList) {
Class clazz = Class.forName(reflectVo.getClassName());
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
if (declaredMethod.getName().equals(reflectVo.getMethodName())){
Object obj = clazz.newInstance();
Object[] values = new Object[1];
values[0] = mqMessage;
//解除成员属性的私有限制
declaredMethod.setAccessible(true);
declaredMethod.invoke(obj,values);
}
}
}
}
}
3.初始化注册类
public class RabbitConfigInitializer implements SmartInitializingSingleton {
private static final Logger logger = LoggerFactory.getLogger(RabbitConfigInitializer.class) ;
private AmqpAdmin amqpAdmin;
private List<MqQueueConfig> queueConfigList;
public RabbitConfigInitializer(AmqpAdmin amqpAdmin, List<MqQueueConfig> queueConfigList) {
this.amqpAdmin = amqpAdmin;
this.queueConfigList = queueConfigList;
}
@Override
public void afterSingletonsInstantiated() {
declareRabbitModule();
}
private void declareRabbitModule() {
if (CollectionUtil.isEmpty(queueConfigList)) {
return;
}
for (MqQueueConfig queueConfig : queueConfigList) {
configParamValidate(queueConfig);
Queue queue = convertQueue(queueConfig);
Exchange exchange = convertExchange(queueConfig);
String routingKey = queueConfig.getRoutingKey();
String queueName = queueConfig.getQueueName();
String exchangeName = queueConfig.getExchangeName();
Binding binding = new Binding(queueName, Binding.DestinationType.QUEUE, exchangeName, routingKey, null);
amqpAdmin.declareQueue(queue);
amqpAdmin.declareExchange(exchange);
amqpAdmin.declareBinding(binding);
}
}
public void configParamValidate(MqQueueConfig queueConfig) {
String routingKey = queueConfig.getRoutingKey();
Assert.isTrue(StrUtil.isNotBlank(routingKey), "RoutingKey 未配置");
Assert.isTrue(StrUtil.isNotBlank(queueConfig.getExchangeName()), "routingKey:{}未配置exchange的name属性");
Assert.isTrue(StrUtil.isNotBlank(queueConfig.getQueueName()), "routingKey:{}未配置exchange的name属性");
}
public Queue convertQueue(MqQueueConfig queueConfig) {
Map<String, Object> arguments = new HashMap<>();
return new Queue(queueConfig.getQueueName().trim(), true, false, false, arguments);
}
public Exchange convertExchange(MqQueueConfig queueConfig) {
AbstractExchange exchange = null;
String exchangeName = queueConfig.getExchangeName();
boolean isDurable = true;
boolean isAutoDelete = false;
Map<String, Object> arguments =new HashMap<>();
switch (queueConfig.getExchangeType()) {
case "DIRECT":// 直连交换机
exchange = new DirectExchange(exchangeName.trim(), isDurable, isAutoDelete, arguments);
break;
case "TOPIC": // 主题交换机
exchange = new TopicExchange(exchangeName.trim(), isDurable, isAutoDelete, arguments);
break;
case "FANOUT": //扇形交换机
exchange = new FanoutExchange(exchangeName.trim(), isDurable, isAutoDelete, arguments);
break;
case "HEADERS": // 头交换机
exchange = new HeadersExchange(exchangeName.trim(), isDurable, isAutoDelete, arguments);
break;
}
return exchange;
}
}