Sring boot RabbitMQ 小思考

2 篇文章 0 订阅
1 篇文章 0 订阅

怎么限制单次获取的消息数量?

在application.yml配置

spring:
  rabbitmq:
  	listener:
      	simple:
        		prefetch: 1 #单次获取的消息数量
        		acknowledge-mode: manual #手动确认

怎么手动确认消息?

@RabbitListener(queues = RabbitConfig.QUEUE_MSM)
@RabbitHandler
public void msmProcess(Message message, Channel channel) throws IOException {
	String msg = new String(message.getBody());
	//TODO deal msg
	//手动确认消息已处理
	channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
	//手动拒绝消息,且rabbitmq服务器不再重新分发该条消息
	channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
}

不用@Bean注解,怎么注册Queue、Exchange、Binding?

spring boot amqp的注解声明那么方便,为什么不使用呢?
因为…项目要求提供注册Queue、Exchange、Binding的api…

@Component
public class RabbitHelper {

	@Autowired
	private AmqpTemplate amqpTemplate;

	@Autowired
	private AmqpAdmin amqpAdmin;

	/**
	 * 发送消息到队列
	 * 
	 * @param exchange
	 * @param routingKey
	 * @param message
	 */
	public void send(String exchange, String routingKey, String message) {
		amqpTemplate.convertAndSend(exchange, routingKey, message);
	}

	/**
	 * 声明队列
	 * 
	 * @param name
	 * @return
	 * @throws Exception
	 */
	public boolean declareQueue(String name) {
		throwEx4Blank(name);
		amqpAdmin.declareQueue(new Queue(name));
		return true;
	}

	/**
	 * 声明路由
	 * 
	 * @param exchange
	 * @return
	 */
	public boolean declareExchange(AbstractExchange exchange) {
		amqpAdmin.declareExchange(exchange);
		return true;
	}

	/**
	 * 声明路由
	 * 
	 * @param name
	 * @param type
	 * @return
	 */
	public boolean declareExchange(String name, String type) {
		throwEx4Blank(name, type);
		type = type.toLowerCase().trim();
		amqpAdmin.declareExchange(getExchangeByType(name, type));
		return true;
	}

	/**
	 * 将队列绑定到Topic类型的路由
	 * 
	 * @param routingKey
	 * @param queue
	 * @param exchange
	 * @return
	 * @throws Exception
	 */
	public boolean bindingTopic(String routingKey, String queue, String exchange) {
		throwEx4Blank(routingKey, queue, exchange);
		Binding binding = BindingBuilder.bind(new Queue(queue)).to(new TopicExchange(exchange)).with(routingKey);
		amqpAdmin.declareBinding(binding);
		return true;
	}

	/**
	 * 将队列绑定到Direct类型的路由
	 * 
	 * @param routingKey
	 * @param queue
	 * @param exchange
	 * @return
	 * @throws Exception
	 */
	public boolean bindingDirect(String routingKey, String queue, String exchange) {
		throwEx4Blank(routingKey, queue, exchange);
		Binding binding = BindingBuilder.bind(new Queue(queue)).to(new DirectExchange(exchange)).with(routingKey);
		amqpAdmin.declareBinding(binding);
		return true;
	}

	/**
	 * 将队列绑定到Fanout类型的路由
	 * 
	 * @param queue
	 * @param exchange
	 * @return
	 */
	public boolean bindingFanout(String queue, String exchange) {
		throwEx4Blank(queue, exchange);
		Binding binding = BindingBuilder.bind(new Queue(queue)).to(new FanoutExchange(exchange));
		amqpAdmin.declareBinding(binding);
		return true;
	}

	/**
	 * 将队列绑定到路由
	 * <p>
	 * 允许的路由类型仅为:TOPIC、DIRECT、FANOUT
	 * </p>
	 * <p>
	 * 当路由类型为FANOUT时,routingKey可为空
	 * </p>
	 * 
	 * @param routingKey
	 * @param queue
	 * @param exchange
	 * @param exchangeType
	 * @return
	 * @throws Exception
	 */
	public boolean binding(String routingKey, String queue, String exchange, String exchangeType) {
		exchangeType = exchangeType.toLowerCase().trim();
		if (ExchangeTypes.TOPIC.equals(exchangeType)) {
			return bindingTopic(routingKey, queue, exchange);
		} else if (ExchangeTypes.DIRECT.equals(exchangeType)) {
			return bindingDirect(routingKey, queue, exchange);
		} else if (ExchangeTypes.FANOUT.equals(exchangeType)) {
			return bindingFanout(queue, exchange);
		} else {
			String msg = "参数错误。exchangeType只能为%s、%s、%s中的一种。";
			String error = String.format(msg, ExchangeTypes.TOPIC, ExchangeTypes.DIRECT, ExchangeTypes.FANOUT);
			throw new IllegalArgumentException(error);
		}
	}

	/**
	 * 将队列绑定到路由
	 * <p>
	 * 允许的路由类型仅为:TOPIC、DIRECT、FANOUT
	 * </p>
	 * <p>
	 * 当路由类型为FANOUT时,routingKey可为空
	 * </p>
	 * 
	 * @param routingKey
	 * @param queue
	 * @param exchange
	 * @return
	 * @throws Exception
	 */
	public boolean binding(String routingKey, String queue, AbstractExchange exchange) {
		String exchangeType = exchange.getType();
		String exchangeName = exchange.getName();
		return binding(routingKey, queue, exchangeName, exchangeType);
	}

	/**
	 * 将队列绑定到路由
	 * <p>
	 * 允许的路由类型仅为:TOPIC、DIRECT、FANOUT
	 * </p>
	 * <p>
	 * 当路由类型为FANOUT时,routingKey可为空
	 * </p>
	 * 
	 * @param routingKey
	 * @param queue
	 * @param exchange
	 * @return
	 * @throws Exception
	 */
	public boolean binding(String routingKey, Queue queue, AbstractExchange exchange) {
		String exchangeType = exchange.getType();
		String exchangeName = exchange.getName();
		String queueName = queue.getName();
		return binding(routingKey, queueName, exchangeName, exchangeType);
	}

	private AbstractExchange getExchangeByType(String name, String type) {
		AbstractExchange exchange = null;
		if (ExchangeTypes.TOPIC.equals(type)) {
			exchange = new TopicExchange(name);
		} else if (ExchangeTypes.DIRECT.equals(type)) {
			exchange = new DirectExchange(name);
		} else if (ExchangeTypes.FANOUT.equals(type)) {
			exchange = new FanoutExchange(name);
		} else if (ExchangeTypes.HEADERS.equals(type)) {
			exchange = new HeadersExchange(name);
		}
		return exchange;
	}

	private void throwEx4Blank(String... strings) {
		for (String s : strings) {
			if (StringUtils.isBlank(s)) {
				throw new IllegalArgumentException("参数错误。所需参数不能为空。");
			}
		}
	}
}

如果不声明消费者,其他的@Bean注解的Queue、Exchange、Binding会生效吗?

问:为什么不声明消费者?
答:1. 消费者 2. 生产者 3. @Bean声明的Queue、Exchange、Binding;三者在各自不同的服务上。
如果你没有声明任何消费者,且没有主动创建rabbitmq连接,那么…你利用注解声明的Queue、Exchange、Binding,其实是不会主动注册到rabbitmq上的。(写博客时所用spring boot amqp版本是2.0.0.RELEASE)
那么解决方案呢?显而易见:主动创建rabbitmq连接

@Autowired
private RabbitTemplate amqpTemplate;

private void explicitOpenMqConnect() {
	//主动创建rabbitmq连接
	amqpTemplate.getConnectionFactory().createConnection();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值