RabbitMq有很多使用方式,里面我将常用的几种方式列出,以便日后回故:
一,原生java API方式 :
maven依赖:
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
</dependency>
生产者:
package com.lyy.rabbitmq.base;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConfirmListener;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ReturnListener;
public class Producer {
public static void main(String[] args) throws Exception, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
//开启消息发送确认模式
channel.confirmSelect();
//增加消息发送确认监听
channel.addConfirmListener(new ConfirmListener() {
@Override
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
System.out.println("成功");
}
@Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
System.err.println("失败");
}
});
//增加return监听(当前的Exchange不存在或者指定的路由Key无匹配)
channel.addReturnListener(new ReturnListener() {
@Override
public void handleReturn(int replyCode, String replyText, String exchange,
String routingKey, AMQP.BasicProperties properties, byte[] body)
throws IOException {
System.err.println("---------handle return----------");
System.err.println("replyCode: " + replyCode);
System.err.println("replyText: " + replyText);
System.err.println("exchange: " + exchange);
System.err.println("routingKey: " + routingKey);
System.err.println("properties: " + properties);
System.err.println("body: " + new String(body));
}
});
String exchange = "test_topic_exchange_01";
String routingKey = "lyy.test";
Map<String, Object> map = new HashMap<>();
map.put("custom", "hehe");
BasicProperties properties = new AMQP.BasicProperties.Builder()
//持久化
.deliveryMode(2)
.contentEncoding("UTF-8")
//消息过期时间
.expiration("10000")
//自定义参数
.headers(map)
.build();
String body = "test ";
//Mandatory:如果为true,则监听器会接收到路由不可达的消息,如果为False,那么Broker端自动删除改消息。
channel.basicPublish(exchange, routingKey,true, properties, body.getBytes());
// channel.close();
// connection.close();
}
}
消费者:
package com.lyy.rabbitmq.base;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Consumer {
public static void main(String[] args) throws Exception, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
connectionFactory.setAutomaticRecoveryEnabled(true);
connectionFactory.setNetworkRecoveryInterval(3000);
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
String exchange = "test_topic_exchange_01";
String exchangeType = "topic";
String queue = "test_queue";
String routingKey = "lyy.#";
channel.exchangeDeclare(exchange, exchangeType);
channel.queueDeclare(queue, true, false, false, null);
channel.queueBind(queue, exchange, routingKey);
//1 限流方式 第一件事就是 autoAck设置为 false
channel.basicQos(0, 1, false);
// 手工签收 必须要关闭 autoAck = false
channel.basicConsume(queue, false, new MyConsumer(channel));
}
}
消费处理类:
package com.lyy.rabbitmq.base;
import java.io.IOException;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
public class MyConsumer extends DefaultConsumer {
private Channel channel;
public MyConsumer(Channel channel) {
super(channel);
this.channel = channel;
}
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
System.out.println(new String(body));
Object object = properties.getHeaders().get("custom");
System.out.println(object.toString());
long deliveryTag = envelope.getDeliveryTag();
System.out.println(deliveryTag);
channel.basicAck(deliveryTag, false);
// channel.basicNack(deliveryTag, false, true);
}
}
二,spring 使用方式 1:
maven 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置类:
package com.lyy.rabbitmq.spring;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Config {
@Bean
public ConnectionFactory connectionFactory(){
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses("127.0.0.1:5672");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
connectionFactory.setVirtualHost("/");
return connectionFactory;
}
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
rabbitAdmin.setAutoStartup(true);
return rabbitAdmin;
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
return rabbitTemplate;
}
}
生产者:
package com.lyy.rabbitmq.spring;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.fasterxml.jackson.databind.ObjectMapper;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Producer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void send() throws Exception {
MessageProperties messageProperties = new MessageProperties();
//下面两句必须加上,消息费才可以传成对应的对象
messageProperties.setContentType("application/json");
messageProperties.getHeaders().put("__TypeId__", "com.lyy.rabbitmq.spring.Order");
Order order = new Order();
order.setId("1");
order.setDes("order test");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(order);
Message message = new Message(json.getBytes(), messageProperties);
rabbitTemplate.convertAndSend("spring-test001", "spring.queue002", message);
}
}
消费者:
package com.lyy.rabbitmq.spring;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.ConsumerTagStrategy;
import org.springframework.amqp.support.converter.ContentTypeDelegatingMessageConverter;
import org.springframework.amqp.support.converter.DefaultJackson2JavaTypeMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Consumer {
@Bean
public TopicExchange exchange001() {
return new TopicExchange("spring-test001", true, false);
}
@Bean
public Queue queue001() {
return new Queue("spring-test001",true);
}
@Bean
public Queue queue002() {
return new Queue("spring-test002",true);
}
@Bean
public Binding binding001() {
return BindingBuilder.bind(queue001()).to(exchange001()).with("spring.queue001");
}
@Bean
public Binding binding002() {
return BindingBuilder.bind(queue002()).to(exchange001()).with("spring.queue002");
}
@Bean
public SimpleMessageListenerContainer messageListener(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
//消息签收模式
container.setAcknowledgeMode(AcknowledgeMode.AUTO);
//监听的队列
container.setQueues(queue001(),queue002());
//监听方法的并发数设置
container.setConcurrentConsumers(1);
container.setMaxConcurrentConsumers(3);
//失败是否重回队列
container.setDefaultRequeueRejected(false);
//消费者标识
container.setConsumerTagStrategy(new ConsumerTagStrategy() {
@Override
public String createConsumerTag(String queue) {
return queue + UUID.randomUUID().toString();
}
});
//使用适配器方式处理消息
MessageListenerAdapter adapter = new MessageListenerAdapter(new MyDelegate());
Map<String, String> queueOrTagToMethodName = new HashMap<String, String>();
queueOrTagToMethodName.put("spring-test001", "processQueueMessage");
queueOrTagToMethodName.put("spring-test002", "processQueueMessage");
//队列和处理方法的对应关系
adapter.setQueueOrTagToMethodName(queueOrTagToMethodName);
//全局的转换器,可以同步配置多个类型的转换器
ContentTypeDelegatingMessageConverter convert = new ContentTypeDelegatingMessageConverter();
//json格式的转换器
// Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
// convert.addDelegate("json", jackson2JsonMessageConverter);
// convert.addDelegate("application/json", jackson2JsonMessageConverter);
//json转对象
Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
DefaultJackson2JavaTypeMapper javaTypeMapper = new DefaultJackson2JavaTypeMapper();
//这个一定要设置,信息所有包路径
javaTypeMapper.setTrustedPackages("*");
//指定映射类的关系
Map<String, Class<?>> idClassMapping = new HashMap<String, Class<?>>();
idClassMapping.put("order", com.lyy.rabbitmq.spring.Order.class);
javaTypeMapper.setIdClassMapping(idClassMapping);
jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper);
convert.addDelegate("application/json", jackson2JsonMessageConverter);
adapter.setMessageConverter(convert);
container.setMessageListener(adapter);
return container;
}
}
消费者代理处理类:
package com.lyy.rabbitmq.spring;
public class MyDelegate {
/**
* 根据发送消息的类型自动调用参数类型匹配的方法
* @param message
*/
public void processQueueMessage(String message) {
System.out.println(message);
}
public void processQueueMessage(Order order) {
System.out.println(order.getDes());
}
}
三,spring 使用方式 ——注解式声明监听:
生产者:
package com.lyy.rabbitmq.springboot;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.test.context.junit4.SpringRunner;
import com.lyy.rabbitmq.spring.Order;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Producer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void sendMessage() {
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("abcd", "zs");
MessageHeaders messageHeaders = new MessageHeaders(headers);
Message<String> message = MessageBuilder.createMessage("spring boot rabittMq ", messageHeaders);
rabbitTemplate.setConfirmCallback(new MyConfirmCallback());
rabbitTemplate.setReturnCallback(new MyReturnCallback());
rabbitTemplate.convertAndSend("springboot-exchanges", "springboot.string",
message, new CorrelationData(UUID.randomUUID().toString()));
}
@Test
public void sendOrder() {
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("abcd", "zs");
MessageHeaders messageHeaders = new MessageHeaders(headers);
Order order = new Order();
order.setId("123456");
Message<Order> message = MessageBuilder.createMessage(order,messageHeaders);
rabbitTemplate.setConfirmCallback(new MyConfirmCallback());
rabbitTemplate.setReturnCallback(new MyReturnCallback());
rabbitTemplate.convertAndSend("springboot-exchanges", "springboot.order",
message, new CorrelationData(UUID.randomUUID().toString()));
}
}
ConfirmCallback:
package com.lyy.rabbitmq.springboot;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.support.CorrelationData;
public class MyConfirmCallback implements ConfirmCallback {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
//消息唯一标识
System.out.println(correlationData);
System.out.println(cause);
if(!ack) {
System.out.println("发送异常,日志记录");
}
}
}
ReturnCallback:
package com.lyy.rabbitmq.springboot;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback;
public class MyReturnCallback implements ReturnCallback {
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println(message);
System.out.println(replyCode);
System.out.println(replyText);
System.out.println(exchange);
System.out.println(routingKey);
}
}
消费者:
package com.lyy.rabbitmq.springboot;
import java.io.IOException;
import java.util.Map;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.lyy.rabbitmq.spring.Order;
import com.rabbitmq.client.Channel;
@Service(value="springbootConsumer")
public class Consumer {
@RabbitListener(bindings = @QueueBinding(value = @Queue(value="springboot-test",durable = "true"),
exchange = @Exchange(name="springboot-exchanges",durable="true",type="topic"),
key="springboot.string"))
@RabbitHandler
public void onMessage(Message<Object> message, Channel channel) throws Exception {
Object object = message.getPayload();
System.out.println(object);
MessageHeaders headers = message.getHeaders();
Object object2 = headers.get("abcd");
System.out.println(object2);
//配置文件中设置的手工签收
channel.basicAck(Long.parseLong(headers.get(AmqpHeaders.DELIVERY_TAG).toString()), false);
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "${spring.rabbitmq.listener.order.queue.name}",
durable="${spring.rabbitmq.listener.order.queue.durable}"),
exchange = @Exchange(value = "${spring.rabbitmq.listener.order.exchange.name}",
durable="${spring.rabbitmq.listener.order.exchange.durable}",
type= "${spring.rabbitmq.listener.order.exchange.type}",
ignoreDeclarationExceptions = "${spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions}"),
key = "${spring.rabbitmq.listener.order.key}"
)
)
@RabbitHandler
public void onOrderMessage(@Payload Order order,
Channel channel,
@Headers Map<String, Object> headers) throws Exception {
System.out.println("--------------------------------------");
System.out.println("消费端order: " + order.getId());
Long deliveryTag = (Long)headers.get(AmqpHeaders.DELIVERY_TAG);
//手工ACK
channel.basicAck(deliveryTag, false);
}
}
application.properties
spring.rabbitmq.addresses=127.0.0.1:5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
spring.rabbitmq.connection-timeout=15000
#producer
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.publisher-returns=true
spring.rabbitmq.template.mandatory=true
#consumer
spring.rabbitmq.listener.simple.acknowledge-mode=manual
spring.rabbitmq.listener.simple.concurrency=5
spring.rabbitmq.listener.simple.max-concurrency=10
#custom
spring.rabbitmq.listener.order.queue.name=springboot-test2
spring.rabbitmq.listener.order.queue.durable=true
spring.rabbitmq.listener.order.exchange.name=springboot-exchanges
spring.rabbitmq.listener.order.exchange.durable=true
spring.rabbitmq.listener.order.exchange.type=topic
spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions=true
spring.rabbitmq.listener.order.key=springboot.order