消息队列的实现 - 实体类

这里写自定义目录标题

  • 前言
    • 创建项目
      • 交换机实体类的创建
      • 队列实体类的创建
      • 绑定实体类的创建
      • 消息实体类的创建
      • 配置全局配置文件
    • 实现接口类
    • 创建接口对应的xml

前言

上一篇博客中我们讲述了, 消息队列的相关知识, 这一篇博客,我们主要讲解消息队列中的实体类的实现

创建项目

因为之前已经有博客写过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;
}

消息实体类的创建

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;
    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;
}

配置全局配置文件

在创建完实体类之后, 需要配置数据库的链接信息, 这里数据库使用的是SQLite , 使用SQLite 而不使用MySQL的原因是, SQLite 更轻量, 因为我们要在数据库中存放一些相关的交换机,绑定, 队列等概念, MySQL我们都知道他是 客户端-服务器的模式, 拿取数据太慢了, 我们消息队列要求速度, 所以使用SQLite

在Java中想要使用SQLite十分简单, 引入SQLlite的依赖即可, 这里给大家放下依赖

<!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->
		<dependency>
			<groupId>org.xerial</groupId>
			<artifactId>sqlite-jdbc</artifactId>
			<version>3.41.0.1</version>
		</dependency>


spring:
  datasource:
    url: jdbc:sqlite:./data/meta.db
    username:
    password:
    driver-class-name: org.sqlite.JDBC

mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml

在resource中创建mapper包, 里面存放对应的注解 (也可以使用MyBatis新版的方式)

实现接口类

我们发现之前使用MySQL的时候, 都是直接写好创建表然后才启动服务器, 在整个项目中只部署一次, 但是我们希望用代码来创建表

package com.example.demo.mqServer.mapper;

public interface MateMapper {

    void createExchangeTable();
    void createQueueTable();
    void createBindingTable();
}

创建接口对应的xml

xml还是不难写的, 只需要与实体类的属性对应上即可,
但是有一个问题被我们忽略了 , 那就是在 交换机和队列中 我们使用 一个属性 是用 哈希表来存储的, 而数据库中是没有哈希表的数据类型的, 我们还要将哈希表转换为, 数据库中的数据类型 , 怎么转换?
答: 我们先补充一个前置知识, 就是 MyBatis 在完成数据库操作的时候,会自动调用对象的get和set方法 , 我们利用这个规则, 将 哈希表 与 数据库数据类型 实现对应
我们使用JSON 来完成 哈希表 与 字符串 之间的相互转换, 在SpringBoot中内置了JSON , 所以我们直接创建 ObjectMapper objectMapper = new ObjectMapper(); 使用对应的方法就行了

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mqServer.mapper.MateMapper">
    <update id="createExchangeTable">
        create table if no exists exchange(
            name varchar(50) primary key,
            type int,
            durable boolean,
            autoDelete boolean,
            arguments varchar(1024)
        );
    </update>
    <update id="createQueueTable">
        create table if no exists queue(
            name varchar(50) primary key,
            durable boolean,
            exclusive boolean,
            autoDelete boolean,
            arguments varchar(1024)
        );
    </update>
    <update id="createBindingTable">
        create table if no exists binding(
            exchangeName varchar(50),
            msgQueueName varchar(50),
            bindingKey varchar(256),
        );
    </update>

</mapper>

你可能感兴趣的:(MQ消息队列,java,spring,boot,开发语言)