RabbitMQ概述
JMS
RabbitMQ快速入门
创建SpringBoot工程,勾选web,RabbitMQ
先配置yaml文件
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
创建包config
创建一个公共配置类,定义一些配置信息
@Configuration
public class RabbitConfig {
/**
* 1、name: 队列名称
* 2、durable: 是否持久化
* 3、exclusive: 是否独享、排外的。如果设置为true,定义为排他队列。则只有创建者可以使用此队列。也就是private私有的。
* 4、autoDelete: 是否自动删除。也就是临时队列。当最后一个消费者断开连接后,会自动删除。
* */
//RabbitMQ队列主题的名称
public static final String RABBITMQ_DEMO_NAME="rabbitmqDemoTopic";
//RabbitMQ的DIRECT交换机名称
public static final String RABBIT_DEMO_DIRECT_EXCHANGE="rabbitmqDemoDirectExchange";
//RabbitMQ的DIRECT交换机和队列绑定的匹配键 DirectRouting
public static final String RABBITMQ_DEMO_DIRECT_ROUTING="rabbitmqDemoDirectRouting";
}
生产者这边创建一个Direct交换机以及队列的配置类
@Configuration
public class DirectRabbitConfig {
@Bean
public Queue rabbitmqDemoDirectQueue(){
/**
* 1、name:队列名称
* 2、durable是否持久化
* 3、exclusive:是否独享、排外的。如果设置为true,定义为排他队列,则只有创建者可以使用此队列
* 4、autoDelete:是否自动删除 也就是临时队列 当最后一个消费者断开连接后 会自动删除
*/
return new Queue(RabbitConfig.RABBITMQ_DEMO_NAME,true,false,false);
}
@Bean
public DirectExchange rabbitmqDemoDirectExchange(){
//Direct交换机
return new DirectExchange(RabbitConfig.RABBIT_DEMO_DIRECT_EXCHANGE,true,false);
}
@Bean
public Binding bindDirect(){
//链式写法 绑定交换机和队列 并设置匹配键
return BindingBuilder
//绑定队列
.bind(rabbitmqDemoDirectQueue())
//到交换机
.to(rabbitmqDemoDirectExchange())
//并设置匹配键
.with(RabbitConfig.RABBITMQ_DEMO_DIRECT_ROUTING);
}
}
创建service类
@Service
public class RabbitMQServiceImpl implements RabbitMQService {
//日期格式化
private static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Resource
private RabbitTemplate rabbitTemplate;
@Override
public String sendMsg(String msg) {
try {
String msgID= UUID.randomUUID().toString().replace("-","").substring(0,32);
String sendTime =sdf.format(new Date());
Map<String,Object> map=new HashMap<>();
map.put("msgId",msgID);
map.put("sendTime",sendTime);
map.put("msg",msg);
rabbitTemplate.convertAndSend(RabbitConfig.RABBIT_DEMO_DIRECT_EXCHANGE,RabbitConfig.RABBITMQ_DEMO_DIRECT_ROUTING,map);
return "OK";
}catch (Exception ex){
ex.printStackTrace();
return "error";
}
}
}
根据业务放在需要用的地方,比如定时任务,或者接口。我这里就简单一点使用Controller层进行发送
@RestController
@RequestMapping("/mall/rabbit")
public class RabbitMQController {
@Resource
private RabbitMQService rabbitMQService;
//发送消息
@PostMapping("/sendMsg")
public String sendMsg(@RequestParam(name="msg") String msg){
return rabbitMQService.sendMsg(msg);
}
}
生产者写完了后,该写消费者代码,@RabbitListener注解写上监听队列的名称,
@Component
@RabbitListener(queues = RabbitConfig.RABBITMQ_DEMO_NAME) //队列名称 可以有多个
public class RabbitConsumer {
@RabbitHandler
public void process(Map map){
System.out.println("消费者从RabbitMQ服务端服务消费者信息:"+map.toString());
}
}
这时候去运行,会发现无法正常运行,为什么会这样了?
答:未在RabbitMQ服务器中创建队列
打开RabbitMQ文件所在位置,打开sbin文件包,运行cmd,如图
输入rabbitmq-plugins enable rabbitmq_management命令安装管理页面的插件
然后双击rabbitmq-server.bat启动脚本,这时候打开浏览器输入
http://localhost:15672
,账户密码默认是guest/guest
点开Queues
要先启动生产者,发一条消息(打开Postman)
在启动工程,进行消费
问题改进
由于队列不存在,启动消费者报错的这个问题。最好的方法是生产者和消费者都尝试创建队列
在文件DirectRabbitConfig中新添加代码
/**
* 自动配置
* 1、RabbitConfiguration
* 2、有自动配置了连接工厂ConnectionFactory
* 3、RabbitProperties:封装了RabbitMQ的配置
* 4、RabbitTemplate:给RabbitMQ发送消息
* 5、AmqpAdmin:RabbitMQ系统管理功能组件
* AmqpAdmin:创建和删除 Queue、Exchange、Binding
* @EnableRabbit+@RabbitListener监听消息内容
*/
@Component
@Configuration
//实现BeanPostProcessor类,使用Bean的生命周期函数
public class DirectRabbitConfig implements BeanPostProcessor {
//这是创建交换机和队列用的rabbitAdmin对象
@Resource
private RabbitAdmin rabbitAdmin;
//初始化rabbitAdmin
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
RabbitAdmin rabbitAdmin=new RabbitAdmin(connectionFactory);
//只有设置为true,spring才能加载RabbitAdmin这个类
rabbitAdmin.setAutoStartup(true);
return rabbitAdmin;
}
//实例化Bean后 也就是Bean的后置处理器
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//创建交换机
rabbitAdmin.declareExchange(rabbitmqDemoDirectExchange());
//创建队列
rabbitAdmin.declareQueue(rabbitmqDemoDirectQueue());
return null;
}
}
这样启动生产者就会自动创建交换机和队列,不用等到发送消息才创建。
消费者也需要添加一些代码
@Component
//@RabbitListener(queues = RabbitConfig.RABBITMQ_DEMO_NAME) //队列名称 可以有多个
//使用queuesToDeclare属性,如果不存在则会创建队列
@RabbitListener(queuesToDeclare = @Queue(RabbitConfig.RABBITMQ_DEMO_NAME))
public class RabbitConsumer {
@RabbitHandler
public void process(Map map){
System.out.println("消费者从RabbitMQ服务端服务消费者信息:"+map.toString());
}
}
现在就不会出问题了
完整代码如下
https://gitee.com/jiang-yingcai011012/rabbit-mq