1 RabbitMQ 安装与启动
-
下载并安装 Eralng(以管理员身份运行安装)
https://www.erlang.org/downloads
-
下载并安装rabbitmq
https://www.rabbitmq.com/download.html
双击安装,注意不要安装在包含中文和 空格的目录下!安装后window服务中就存在rabbitMQ了,并且是启动状态。
-
安装管理界面(插件)
进入rabbitMQ安装目录的sbin目录,输入命令
rabbitmq‐plugins enable rabbitmq_management
-
重新启动服务
-
打开浏览器,地址栏输入http://127.0.0.1:15672
-
输入用户名和密码,都为guest 进入主界面:
2 RabbitMQ 三种模式
2.1 直连模式(Direct)
我们需要将消息发给唯一一个节点时使用这种模式,这是最简单的一种形式。
有如下特点:
- 一般情况可以使用rabbitMQ自带的Exchange:” “(该Exchange的名字为空字符串,下文称其为default Exchange)。
- 这种模式下不需要将Exchange进行任何绑定(binding)操作
- 消息传递时需要一个“RouteKey”,可以简单的理解为要发送到的队列名字。
- 如果vhost中不存在RouteKey中指定的队列名,则该消息会被抛弃。
2.2 分列模式(Fanout)
当我们需要将消息一次发给多个队列时,需要使用这种模式。
有如下特点:
- 可以理解为路由表的模式
- 这种模式不需要RouteKey
- 这种模式需要提前将Exchange与Queue进行绑定,一个Exchange可以绑定多个 Queue,一个Queue可以同多个Exchange进行绑定。
- 如果接受到消息的Exchange没有与任何Queue绑定,则消息会被抛弃。
2.3 主题模式(Topic)
任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue 上
有如下特点:
- 这种模式较为复杂,简单来说,就是每个队列都有其关心的主题,所有的消息都带有一 个“标题”(RouteKey),Exchange会将消息转发到所有关注主题能与RouteKey模糊匹配的 队列。
- 这种模式需要RouteKey,也许要提前绑定Exchange与Queue。
- 在进行绑定时,要提供一个该队列关心的主题,如“#.log.#”表示该队列关心所有涉及 log的消息(一个RouteKey为”MQ.log.error”的消息会被转发到该队列)。
- “#”表示0个或若干个关键字,“”表示一个关键字。如“log.”能与“log.warn”匹配,无法 与“log.warn.timeout”匹配;但是“log.#”能与上述两者匹配。
- 同样,如果Exchange没有发现能够与RouteKey匹配的Queue,则会抛弃此消息
3 RabbitMQ 使用场景
- 用户注册,发送手机验证码,先存入Redis并再发送到RabbitMQ。
- 订单生成后手机短信通知、物流安排等。
4 RabbitMQ 代码实现
4.1 用户服务实现
4.1.1 引入redis和amqp依赖
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐data‐redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐amqp</artifactId>
</dependency>
...
4.1.2 修改application.yml
...
spring:
redis:
host: 192.168.184.134
rabbitmq:
host: 192.168.184.134
...
4.1.3 UserService中新增方法,用于发送短信验证码
...
public class UserService{
...
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private RabbitTemplate rabbitTemplate;
...
/**
* 发送短信验证码
* @param mobile 手机号
*/
public void sendSms(String mobile){
//1.生成6位短信验证码
Random random=new Random();
int max=999999;//最大数
int min=100000;//最小数
int code = random.nextInt(max);//随机生成
if(code<min){
code=code+min;
}
System.out.println(mobile+"收到验证码是:"+code);
//2.将验证码放入redis
redisTemplate.opsForValue().set("smscode_"+mobile, code+"" ,5,TimeUnit.MINUTES );//五分钟过期
//3.将验证码和手机号发动到rabbitMQ中
Map<String,String> map=new HashMap();
map.put("mobile",mobile);
map.put("code",code+"");
rabbitTemplate.convertAndSend("sms",map);
}
/**
* 增加
* @param user 用户
* @param code 用户填写的验证码
*/
public void add(User user,String code) {
//判断验证码是否正确
String syscode = (String)redisTemplate.opsForValue().get("smscode_" + user.getMobile());
//提取系统正确的验证码
if(syscode==null){
throw new RuntimeException("请点击获取短信验证码");
}
if(!syscode.equals(code)){
throw new RuntimeException("验证码输入不正确");
}
user.setId(idWorker.nextId()+"");
user.setFollowcount(0);//关注数
user.setFanscount(0);//粉丝数
...
userDao.save(user);
}
...
}
4.2 消息服务实现
4.2.1 引入amqp依赖
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐amqp</artifactId>
</dependency>
...
4.2.1 修改application.yml
...
spring:
rabbitmq:
host: 192.168.184.134
...
4.3 消息监听类
/**
* 短信监听类
*/
@Component
@RabbitListener(queues = "sms")
public class SmsListener {
/**
* 发送短信
* @param message
*/
@RabbitHandler
public void sendSms(Map<String,String> message){
System.out.println("手机号:"+message.get("mobile"));
System.out.println("手机号:"+message.get("mobile"));
//调用阿里云通讯接口
...
}
}