RebbitMq 的使用

springboot下集成RabbitMq 

RabbitMq 安装需要Erlang环境,

RabbitMq 发送信息流程

消息封装后--发送到--交换Exchange--路由key (Exchange和Queue绑定的值)--Queue(消息放在Queue上面)

 

如果使用maven 的话pom.xml里面添加

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

如果是build.gradle

compile('org.springframework.boot:spring-boot-starter-amqp')

application.properties

把 队列(Queue),交换(Exchange),路由绑定(Binding)写在了配置文件里,可以灵活一点,也可以在RabbitmqConfig把名字固定写死,

spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.listener.concurrency=10
spring.rabbitmq.listener.max-concurrency=20
spring.rabbitmq.listener.prefetch=5

#spring.rabbitmq.listener.acknowledge-mode=manual
mq.env=local
log.user.queue.name=${mq.env}.log.user.queue
log.user.exchange.name=${mq.env}.log.user.exchange
log.user.routing.key.name=${mq.env}.log.user.routing.key

Rabbitmq的配置类。

RabbitmqConfig

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;

import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;



@Configuration
public class RabbitmqConfig {

private static final Logger log= LoggerFactory.getLogger(RabbitmqConfig.class);

@Autowired
private Environment env;

@Autowired
private CachingConnectionFactory connectionFactory;

@Autowired
private SimpleRabbitListenerContainerFactoryConfigurer factoryConfigurer;

/**
 * 单一消费者
 * @return
 */
@Bean(name = "singleListenerContainer")
public SimpleRabbitListenerContainerFactory listenerContainer(){
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setMessageConverter(new Jackson2JsonMessageConverter());
    factory.setConcurrentConsumers(1);
    factory.setMaxConcurrentConsumers(1);
    factory.setPrefetchCount(1);
    factory.setTxSize(1);
   // factory.setAcknowledgeMode(AcknowledgeMode.AUTO);
    //AcknowledgeMode.NONE:不确认
    //AcknowledgeMode.MANUAL:自动确认
    //AcknowledgeMode.AUTO:手动确认
    factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    return factory;
}

/**
 * 多个消费者
 * @return
 */
@Bean(name = "multiListenerContainer")
public SimpleRabbitListenerContainerFactory multiListenerContainer(){
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factoryConfigurer.configure(factory,connectionFactory);
    factory.setMessageConverter(new Jackson2JsonMessageConverter());
    factory.setAcknowledgeMode(AcknowledgeMode.NONE);
    factory.setConcurrentConsumers(env.getProperty("spring.rabbitmq.listener.concurrency",int.class));
    factory.setMaxConcurrentConsumers(env.getProperty("spring.rabbitmq.listener.max-concurrency",int.class));
    factory.setPrefetchCount(env.getProperty("spring.rabbitmq.listener.prefetch",int.class));
    
    return factory;
  
}

@Bean
public RabbitTemplate rabbitTemplate(){
    connectionFactory.setPublisherConfirms(true);
    connectionFactory.setPublisherReturns(true);
    RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
    rabbitTemplate.setMandatory(true);
    rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
        @Override
        public void confirm(CorrelationData correlationData, boolean ack, String cause) {
            log.info("消息发送成功:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
        }
    });
    rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
        @Override
        public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
            log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}",exchange,routingKey,replyCode,replyText,message);
        }
    });
    return rabbitTemplate;
}

/**
 * Queue构造参数详解:
 * 参数:
 * name:队列的名称
 * durable:设置是否持久化。持久化的队列会存盘,在服务器重启的时候可以保证不丢失相关信息
 * exclusive:设置是否排他。如果一个队列被声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除
 * autoDelete:设置是否自动删除。自动删除的前提是:至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除
 */
@Bean
public Queue logUserQueue() {
	return new Queue(env.getProperty("log.user.queue.name"),true);
}


/**
 * 以DirectExchange为例构造参数详解:
 * 参数:
 * name:交换机的名称
 * durable:设置是否持久化。持久化可以将交换机存盘,在服务器重启的时候不会丢失相关信息
 * autoDelete:设置是否自动删除,自动删除的前提是至少有一个队列或者交换机与这个交换机绑定,之后所有与这个交换机绑定的队列或者交换机都与此解绑
 */
@Bean
public DirectExchange logUserExchange() {
	return new DirectExchange(env.getProperty("log.user.exchange.name"),true,false);
}

@Bean
public Binding logUserBinding() {
	return BindingBuilder.bind(logUserQueue()).to(logUserExchange()).with(env.getProperty("log.user.routing.key.name"));
}

}

我把写成一个方法里面,

	
public  void rabbitTemplateUtils(User user) throws JsonProcessingException {
	
	 rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
	  rabbitTemplate.setExchange(env.getProperty("log.user.exchange.name"));
	  rabbitTemplate.setRoutingKey(env.getProperty("log.user.routing.key.name"));
	
	  Message message=MessageBuilder.withBody(objectMapper.writeValueAsBytes(user)).setDeliveryMode(MessageDeliveryMode.PERSISTENT).build();
	  message.getMessageProperties().setHeader(AbstractJavaTypeMapper.DEFAULT_CONTENT_CLASSID_FIELD_NAME, MessageProperties.CONTENT_TYPE_JSON);

}
	                user.setName(name);
        			user.setPassword(password);
        			user.setDesc("frist test");
        			user.setId(1);
        			rabbitTemplateUtils(user);

实体类

public class User {
	private int id;
	private String name;
	private String password;
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	private String desc;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDesc() {
		return desc;
	}
	public void setDesc(String desc) {
		this.desc = desc;
	}
}

监听接受到的消息

1.

import java.io.IOException;
import org.slf4j.Logger; import org.slf4j.LoggerFactory; 
import org.springframework.amqp.rabbit.annotation.RabbitListener; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.messaging.handler.annotation.Payload; 
import org.springframework.stereotype.Component;
import com.example.demo.image.entity.User;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
  
  @Component 
  public class CommonMqListener {
  
  private static final Logger log=LoggerFactory.getLogger(CommonMqListener.class);
  
  @Autowired 
  private ObjectMapper objectMapper;


	/*
	 * 监听消费用户日志
	 * 
	 * @param message
	 */
	 
		  @RabbitListener(queues = "${log.user.queue.name}",containerFactory ="singleListenerContainer") 
		  public void consumeUserLogQueue(@Payload byte[] message) throws JsonParseException, JsonMappingException, IOException{
			  User user=objectMapper.readValue(message, User.class);

				  System.out.println("user的id:"+user.getId());
				  System.out.println("user的name:"+user.getName());
				  System.out.println("user的password:"+user.getPassword());
				  System.out.println("user的desc:"+user.getDesc());
				  System.out.println("------------------------------------------");
			
		  } 
		  }
		 

2.或者继承ChannelAwareMessageListener

这个可以手动回复ack,需要在RabbitmqConfig里面的 factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);设置AcknowledgeMode.MANUAL

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.example.demo.image.entity.User;
import com.rabbitmq.client.Channel;

@Component
public class RebbitMqListenerOne implements ChannelAwareMessageListener {
	@RabbitListener(queues = "${log.user.queue.name}",containerFactory ="singleListenerContainer") 
	public void onMessage(Message message, Channel channel) throws Exception {
		System.out.println("消息体:----"+new String(message.getBody()));
		byte[] bytem=message.getBody();
		User user=JSON.parseObject(bytem,User.class);
		
			System.out.println("消息体:用户id----"+user.getId());
			System.out.println("消息体:用户名字----"+user.getName());
			System.out.println("消息体:用户名字----"+user.getPassword());
			System.out.println("消息体:用户描述----"+user.getDesc());
			/**
			 * 确认消息
			 * BasicAck方法的第二个参数 multiple 取值为 false 时,表示通知 RabbitMQ 当前消息被确认;
			 * 如果为 true,则额外将比第一个参数指定的 delivery tag 小的消息一并确认。(批量确认针对的是整个信道)
			 */
			channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
	
			/**
			 * 取消确认
			 * 第一个参数指定 delivery tag,
			 * 第二个参数说明如何处理这个失败消息。
			 * requeue 值为 true 表示该消息重新放回队列头,值为 false 表示放弃这条消息。
			 */
		//	channel.basicReject(deliveryTag, requeue);
		
		
		
		
	}

}

这个例子可以正常发送信息,接受信息。但是有一个问题(不是接受发送的问题),看你们能碰到不。

其中参考了一些文章,忘记了出处,如果需要写明备注,请留意。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RabbitMQ是一个使用Erlang实现的高并发高可靠AMQP消息队列服务器。它支持消息的持久化、事务、拥塞控制、负载均衡等特性,使得RabbitMQ在各种应用场景下被广泛使用。RabbitMQ与Erlang和AMQP密切相关。 Erlang是一种编程语言,它特别适合构建高并发、分布式、实时的系统。RabbitMQ使用Erlang作为其底层开发语言,这使得它能够充分利用Erlang在并发处理和容错性方面的优势。 AMQP(Advanced Message Queuing Protocol)是一个开放标准的消息队列协议,用于在应用程序之间进行可靠的消息传递。RabbitMQ实现了AMQP协议,这意味着它可以与其他遵循AMQP协议的应用程序进行通信,实现可靠的消息传递机制。 要使用RabbitMQ,可以通过Docker安装,使用以下命令运行一个带有管理界面的RabbitMQ容器: ``` docker run -itd --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management ``` 在编写RabbitMQ程序时,可以利用其支持的多种消息模型,例如发布-订阅模型、工作队列模型、路由模型等,根据具体需求选择合适的模型来实现消息传递。 在配置RabbitMQ环境时,可以设置RABBITMQ_SERVER环境变量,并将RabbitMQ的安装路径添加到系统的path变量中,以方便在命令行中直接使用RabbitMQ命令。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [RabbitMQ使用详解](https://blog.csdn.net/qq_43410878/article/details/123656765)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值