前言
上一篇博客中我们讲述了, 消息队列的相关知识, 这一篇博客,我们主要讲解消息队列中的实体类的实现
创建项目
因为之前已经有博客写过SpringBoot的创建了, 这里就不过多叙述了
1: 先创建一个SpringBoot项目 ,
2: 依赖至少选择 SpringWeb 与MyBatis俩个依赖 (我里面使用了Lombok , 没有的也没关系)
3: 创建相关的交换机, 队列 , 绑定, 消息, 等实体类
交换机实体类的创建
对于交换机 , 我们要有交换机名称, 交换机的类型, 交换机时候持久化, 是否自动删除, 是否配置额外参数.这些字段
package com.example.demo.mqServer.core;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
// 代表交换机的类
public class Exchange {
// 交换机名字, 唯一标识
private String name;
// 交换机的类型
private ExchangeType type = ExchangeType.direct;
//判断是否要持久化
private boolean durable = false;
//判断是否自动删除
private boolean autoDelete =false;
//交换机指定的额外参数
// 为了把argument存到数据库中, 要使用JSON转成字符串
private Map<String,Object> arguments = new HashMap<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ExchangeType getType() {
return type;
}
public void setType(ExchangeType type) {
this.type = type;
}
public boolean isDurable() {
return durable;
}
public void setDurable(boolean durable) {
this.durable = durable;
}
public boolean isAutoDelete() {
return autoDelete;
}
public void setAutoDelete(boolean autoDelete) {
this.autoDelete = autoDelete;
}
public String getArguments() {
// 将当前的getArguments从map, 转换成String
// SpringBoot 集成了JSON
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.writeValueAsString(arguments);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return "{}";
}
public void setArguments(String argumentsJson) {
ObjectMapper objectMapper = new ObjectMapper();
try {
this.arguments = objectMapper.readValue(argumentsJson, new TypeReference<HashMap<String, Object>>() {
});
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
package com.example.demo.mqServer.core;
public enum ExchangeType {
direct(0),
fanout(1),
topic(2);
private final int type;
ExchangeType(int type) {
this.type = type;
}
}
队列实体类的创建
对于队列,来说, 它的属性值 与 交换机很类似
package com.example.demo.mqServer.core;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
// 代表队列
public class MSGQueue {
// 队列名字, 唯一标识
private String name;
//判断是否要持久化
private boolean durable = false;
// 判断该队列是否被独占
private boolean exclusive = false;
//判断是否自动删除
private boolean autoDelete =false;
//队列指定的额外参数
private Map<String,Object> arguments = new HashMap<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isDurable() {
return durable;
}
public void setDurable(boolean durable) {
this.durable = durable;
}
public boolean isExclusive() {
return exclusive;
}
public void setExclusive(boolean exclusive) {
this.exclusive = exclusive;
}
public boolean isAutoDelete() {
return autoDelete;
}
public void setAutoDelete(boolean autoDelete) {
this.autoDelete = autoDelete;
}
public String getArguments() {
// 将当前的getArguments从map, 转换成String
// SpringBoot 集成了JSON
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.writeValueAsString(arguments);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return "{}";
}
public void setArguments(String argumentsJson) {
ObjectMapper objectMapper = new ObjectMapper();
try {
this.arguments = objectMapper.readValue(argumentsJson, new TypeReference<HashMap<String, Object>>() {
});
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
绑定实体类的创建
而对于绑定来说, 它的属性值很简单, 他只需要交换机的名称,队列名称,和双方的暗号即可
package com.example.demo.mqServer.core;
import lombok.Data;
// 绑定
@Data
public class Binding {
// 交换机名称
private String exchangeName;
// 队列名称
private String msgQueueName;
// 交换机与队列绑定关键字
private String bindingKey;
}
消息实体类的创建
对于消息我们是这样设计的, 我们将消息以二进制数据的形式存储到文件中,所以 消息的属性值有 : 消息正文 - byte数组, 消息属性 - 文章ID, 文章暗号(routingKey 帮助将这个消息发送给那个队列) , 还有消息是否需要持久化, 和消息文章的开头 与结尾 ,最后一个消息的删除(对于消息的删除 ,我们采取逻辑删除的方式 , 0x1表示有效 0x0表示无效)
对于消息来说, 我们还要让他实现Serializable接口,以方便后序我们实例化它
package com.example.demo.mqServer.core;
import lombok.Data;
import java.io.Serializable;
import java.util.UUID;
// 使用标准库中的序列化和反序列化
// 消息
@Data
public class Message implements Serializable {
//消息的属性 - 防止拿到空
private BasicProperties basicProperties = new BasicProperties();
// 消息的正文
private byte[] body;
//偏移量 , beg,表示消息开头到文件开头有多少个字节 , End表示消息结尾到文件开头有多少个字节
// 前闭后开区间
//这俩个属性不需要序列化, 因为不往硬盘中存储
private transient long offsetBeg;//transient为反序列化
private transient long offsetEnd;
// 用字节, 来表示是否逻辑删除 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- 作为前缀.
message.basicProperties.setMessageId("M-"+UUID.randomUUID().toString());
message.basicProperties.setRoutingKey(RoutingKey);
message.body = body;
// 此处是把 body 和 basicProperties 先设置出来. 他俩是 Message 的核心内容.
// 而 offsetBeg, offsetEnd, isValid, 则是消息持久化的时候才会用到. 在把消息写入文件之前再进行设定.
// 此处只是在内存中创建一个 Message 对象.
return message;
}
public void setMessageId(String messageId){
basicProperties.setMessageId(messageId);
}
public String getMessageId(){
return basicProperties.getMessageId();
}
public void setRoutingKey(String routingKey){
basicProperties.setRoutingKey(routingKey);
}
public String getRoutingKey(){
return basicProperties.getRoutingKey();
}
public void setDeliverMode(int deliverMode){
basicProperties.setDeliverMode(deliverMode);
}
public int getDeliverMode(){
return basicProperties.getDeliverMode();
}
}
package com.example.demo.mqServer.core;
import lombok.Data;
import java.io.Serializable;
@Data
public class BasicProperties implements Serializable {
// 唯一身份表示, 使用UUID
private String messageId;
// 与BindingKey 对暗号的
// 如果是 direct 则是转发的队列名
// 如果是 Topic 则是对应的Sting
// 如果是 fanout 则无意义
private String routingKey;
// 判断是否要持久化, 1代表持久化
private int deliverMode =1;
}
小结
对于4个实体类,创建的是最基础的接下来, 我们将这些实体类分别存储到,数据库与文件中.下一篇博客见