Mq消息队列
基本入门
生成者发送消息
@RestController
public class TestController {
@Resource
private RabbitTemplate rabbitTemplate;// 操作mq 消息投递的
@GetMapping("/send")
public String testSend(){
String uuid = UUID.randomUUID().toString();
for(int i=0;i<10;i++){
System.out.println("消息发送时间:" + System.currentTimeMillis());
// 直接向指定的队列投递消息
rabbitTemplate.convertAndSend("heima-queue","hello world" + (i+1));
}
return "ok";
}
}
消费端接收信息
@RabbitListener(queues = "heima-queue") // 监听指定队列
public void receive(String msg, Channel channel, Message message) throws IOException {
//会话唯一ID
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
// System.out.println(1/0);// 模拟业务代码 出现异常
System.out.println("deliveryTag = "+deliveryTag+"-------------------message:" +msg);
channel.basicAck(deliveryTag,false);// 手动确认ack 通知broker 删除当前消息
// multiple:是否批量处理.true: 一次性将ack所有小于deliveryTag的消息删除
// false 从 deliveryTag 消息索引开始 一条一条确认 删除
}catch (Exception e){
// 消息 重新放回队列机制配置
// channel.basicNack(deliveryTag,false,false);// 第三个参数 : true 表示 出现代码业务一次 消息 重新放回队列中 再次获取
}
}
channel.basicNack(deliveryTag,false,true);
//requeue=true 表示 放回到队列中,如果 第三个参数 false 那么此消息不会放回队列中! 队列会直接删除此消息
添加AMQP的启动器pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
在application.yml
中添加RabbitMQ地址: 手动在控制台 新建一个虚拟机 /heima
server:
port: 8081
spring:
application:
name: producer-application
rabbitmq:
virtual-host: /heima <!--队列名字->
username: guest
password: guest
addresses: 127.0.0.1:5672
listener:
direct:
acknowledge-mode: manual # 消费者端 手动确认ack broker队列消息手动通知删除
基于SpringBoot实现邮件发送
提供方
package com.itheima.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.entity.PageQueryBean;
import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private RabbitTemplate rabbitTemplate;//这个的话是AmqpTemplate的实现类
@Override
public void addUser(User user)
String userName = user.getUserName();
String s = UUID.randomUUID().toString();
//生成随机数字把数字和刚刚注册的名字传到消息队列中
//这里是把map集合当作参数发了过去
HashMap<Object, Object> map = new HashMap<>();
map.put(userName, s);
rabbitTemplate.convertAndSend("bocai1",map);//将map放到消息队列中
}
}
消费方
package com.itheima.db;
import com.rabbitmq.client.Channel;
//import com.rabbitmq.client.MessageProperties;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* @program: demo-parent
* @description: 发送邮件类
* @author: Mr.Wang
* @create: 2020-11-02 22:43
**/
@Component
public class SendEmail {
@Autowired
JavaMailSenderImpl javaMailSender;//这个是发送邮件的类
@RabbitListener(queues = "bocai1")//用来获取消息队列上的数据
//map是要和传过来的参数类型一样
public void email(Map<String, String> map, Channel channel, Message message) throws IOException {
try {
channel.basicAck(deliveryTag, false);
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
//获得从消息队列中取得的map值
Set<String> keySet = map.keySet();
Iterator<String> iterator = keySet.iterator();
String key = null;
String value = null;
while (iterator.hasNext()) {
key = iterator.next();
value = map.get(key);
}
simpleMailMessage.setSubject("传智健康官方邮件");
simpleMailMessage.setText("你好"+key+",请保存好验证码:"+value+",打死都不能泄露给你的同桌");
simpleMailMessage.setTo("1046846579@qq.com");
simpleMailMessage.setFrom("13971007912@163.com");
//进行发送邮件
javaMailSender.send(simpleMailMessage);
} catch (IOException e) {
e.printStackTrace();
channel.basicNack(deliveryTag, false, true);
}
}
}
邮件发送的yml依赖
spring
mail:
username: 13971007912@163.com
password: HZCHOWHDDQTUGJKH # 自己的邮件授权码
host: smtp.163.com
properties:
mail:
smtp:
ssl:
enable: true
基本入门2
我们只需要在消息队列上配置好用户名以及virtual hosts就行接下来消息队列名称都由代码实现
yml
rabbitmq:
host: 192.168.206.99 # mq的地址
username: heima #账号
password: heima #密码
virtual-host: /hehe #虚拟路径我们配置的名称
提供方
提供方通过这个引入mq
@Autowired
private AmqpTemplate amqpTemplate;
通过amqpTemplate.convertAndSend()来使用
//使用三元运算符获取是否上下架
String routingKey = saleable ? "item.up" : "item.down";
amqpTemplate.convertAndSend("jiaohuanji",routingKey,id)
参数说明:
jiaohuanji ----->指的是 会自动生成叫做 “jiaohuanji”的交换机名称
routingKey -----> 这里用的是三元运算符来指定是用 item.up 还是 item.down 。后面获取mq消息的时候会用到(我理解的是名称)
id -----> 我们需要传的参数
依赖
<!-- 消息队列-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
消费方
用@RabbitListener来监听消息队列
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "item.up.queue", durable = "true"),
exchange = @Exchange(name = "jiaohuanji", type = ExchangeTypes.TOPIC),
key = "item.up"))
public void up(Long id) {
if (id != null) {
//商品上架,我们需要新增到索引库
indexService.saveGoodsById(id);
}
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "item.down.queue", durable = "true"),
exchange = @Exchange(name = "jiaohuanji", type = ExchangeTypes.TOPIC),
key = "item.down"))
public void down(Long id) {
indexService.deleteGoodsById(id);
}
参数说明
item.down.queue -------》是我们创建消息队列的名称(这里就是创建,不需要提前创建)
jiaohuanji -------》这个就是我们在yml文件中配置的交换机名称
key = “item.down” -------》这里的item.down就是用来匹配提供方放入的第二个参数
Long id -------》这里的参数类型在于我们消息队列上传的什么类型这里就接受什么类型
依赖
<!-- 消息队列-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>