目录
一、创建项目
二、创建核心类
🍅 1、 编写交换机类,Exchange
🍅 2、编写存储消息的队列,MSGQueue
🍅 3、编写绑定类,binding
🍅 4、编写消息,Message
一、创建项目
二、创建核心类
代码解释主要在注释上面,注意一下注释
核心类主要是在服务器模块中的。
主要是以下几个类
* 交换机 exchange
* 队列 queue
* 绑定 binding
* 消息message
🍅 1、 编写交换机类,Exchange
首先编写一个交换机类型的类,ExchangeType
是一个枚举类型。
public enum ExchangeType {
DIRECT(0),
FANOUT(1),
TOPIC(2);
private final int type;
private ExchangeType(int type){
this.type = type;
}
}
下面我这里直接用了Lombok的@Data组合注解注解代替了getter和setter方法,不了解的可以直接generate生产getter和setter方法,然后
关于Lombok不理解的可以参考SpringBoot日志文件_️藿香正气水的博客-CSDN博客,使用需要另外在pom.xml文件添加Lombok依赖
/*
* 表示一个交换机
* */
@Data
public class Exchange {
// 此处使用name,来作为交换机的身份标识(是唯一的)
private String name;
// 交换机类型:DIRECT,FANOUT,TOPIC
// 使用枚举类型来表示
private ExchangeType exchangeType = ExchangeType.DIRECT;
// 表示该交换机是否要持久化存储,true表示需要持久化;false表示不必持久化
// 有的数据是需要持久化存储的,有的不要。所以设置一个开关,
// 用户在使用的时候就可以选择是否真的需要持久化操作
private boolean durable = false;
}
🍅 2、编写存储消息的队列,MSGQueue
/*
* 表示一个存储消息的队列
* MSG => Message
* */
public class MSGQueue {
// 表示队列的身份标识
private String name;
// 标识队列是否持久化,true标识持久化保存,false标识不持久化
private boolean durable;
}
🍅 3、编写绑定类,binding
/*
* 表示队列和交换机之间的关联关系
* */
@Data
public class Binding {
// binding依附于Exchange和Queue
// binding和交换机和队列有关,所以就需要定义这两个name
private String exchangename;
private String queueName;
// bindingKey,匹配了才能绑定
private String bindingKey;
}
🍅 4、编写消息,Message
主要包含两个部分:
* 属性部分
关于属性部分,创建一个BasicProperties类,编写message的属性:
关于三种交换机机型,参考项目实战 — 消息队列(1) {需求分析}_️藿香正气水的博客-CSDN博客
@Data public class BasicProperties { // 消息的唯一身份标识, // 此处要保证id唯一性,使用UUID来作为messageif private String messageId; // 消息上带有的内容,和bindingKey做匹配 // 如果当前的交换机型是DIRECT,此时roitingkey就标识要转发的队列名 // 如果当前的交换机型是FANOUT,此时roitingkey就无意义 // 如果当前的交换机型是TOPIC,此时roitingkey就要和bindingKey做匹配,符合要求才能转发 private String routingKey; // 这个属性表示消息是否要持久化,1标识不持久化 ,2标识持久化 private int deliverMode = 1; }
* 正文部分
/*
* 表示一个要传递的消息
* 主要包含两个部分,一个属性部分,一个正文部分
* 属性部分BasicProperties
* 正文部分byte[]
* * 此处的Message是需要能够在网络中传输的,还要写入到文件中
* 所以需要针对Message进行序列化和反序列化,使用标准库自带的序列化/反序列化操作
* */
@Data
public class Message implements Serializable { //实现该接口,就能实现序列化/反序列化,不需要重写其中的任何方法
private BasicProperties basicProperties;
private byte[] body;
// 下面是辅助性属性
// Message后续会存储到文件中(持久化)
// 一个文件中会存储很多消息,
// 消息的具体位置使用下面的两个偏移量来进行表示
// [offsetBegin,offsetEnd)
// 这两个属性,主要是为了让内存中的Message对象,能够快速的找到对应的硬盘上的Message的位置
// 所以并不需要被序列化保存到文件中,该消息一旦被写入到文件之后,所有消息就固定了,并不需要被单独存储
// 加上transient这两个属性就不会被序列化
private transient long offsetBegin = 0; //消息数据的开头距离文件开头的位置偏移(字节)
private transient long offsetEnd = 0; //消息数据的结尾距离文件开始的位置偏移(字节)
// 使用这个属性表示该消息在文件中是否是有效的消息(逻辑删除)
// 0x1表示有效,0x0表示无效
// 逻辑删除就是,删除数据不是真的删除,而是把需要删除的信息标记成无效
private byte isValid = 0x1;
// 创建一个工厂方法,让工厂方法帮我们封装以下Message对象的过程
// 该方法创建的Message对象,会自动生成唯一的MessageId
// 如果routingKey和basicProperties里面的routingKey冲突,以外面的为主
public static Message createMessageWithId(String routingKey,BasicProperties basicProperties,byte[] body){
Message message = new Message();
if(basicProperties != null){
message.setBasicProperties(basicProperties);
}
// 此处生成的MessageId以M-作为前缀
// 为了和后续别的uid进行区分
message.setMessageId("M-"+ UUID.randomUUID());
message.basicProperties.setRoutingKey(routingKey);
message.body = body;
// 此处主要是把消息和body和属性设置出来,是Message的核心内容
// 其他的offsetBegin等是在消息持久化的时候才会用到
return message;
}
// 下面设置一些getter和Setter方法拿到
public String getMessage(){
return basicProperties.getMessageId();
}
public void setMessageId(String messageId){
basicProperties.setMessageId(messageId);
}
// routingKey让消息和bindingKey做匹配
public String getRoutingKey(){
return basicProperties.getRoutingKey();
}
public void setRoutingKey(String routingKey){
basicProperties.setRoutingKey(routingKey);
}
// deliverMode是为了判断该消息是否要持久化
public int getDeliverMode(){
return basicProperties.getDeliverMode();
}
public void setDeliverMode(int mode){
basicProperties.setDeliverMode(mode);
}
}