从 0 到 1 ,手把手教你编写《消息队列》项目(Java实现) —— 创建项目 / 创建核心类

news2024/11/25 14:34:12

文章目录

  • 一、创建SpringBoot项目
  • 二、创建核心类
    • 创建 Exchange类
    • 创建 MSGQueue类
    • 创建 Binding类
    • 创建Message类


一、创建SpringBoot项目

在项目中添加这四个依赖!
在这里插入图片描述


二、创建核心类

交换机 :Exchange
队列 :Queue
绑定关系: Binding
消息 :Message
这些核心类都存在于 BrokerServer 中.

先创建出服务器与客户端的包.
再在服务器中创建 core包,用来存放这些核心类.
在这里插入图片描述


创建 Exchange类

首先考虑,咱们在此处共实现了三种交换机类型,所以咱们可以创建一个枚举类来表示交换机类型.

/**
 * 表示交换机类型
 */
public enum ExchangeType {
    DIRECT(0),
    FANOUT(1),
    TOPIC(2);

    private final int type;

    private ExchangeType(int type) {
        this.type = type;
    }

    public int getType() {
        return type;
    }
}

咱们再考虑,Exchange类中有哪些属性?

  • 1.name,当作交换机的唯一身份标识
  • 2.ExchangeType,表示交换机类型
  • 3.durable,表示这个交换机是否需要持久化存储
  • 4.autoDelete,表示该交换机在无人使用后,是否会自动删除
  • 5.arguments,表示后续的一些拓展功能
/**
 * 表示一个交换机
 * 交换机的使用者是生产者
 */
@Data
public class Exchange {
    // 此处使用 name 作为交换机的身份标识,(唯一的)
    private String name;

    // 交换机类型,DIRECT,FANOUT,TOPIC
    private ExchangeType type = ExchangeType.DIRECT;

    // 该交换机是否要持久化存储,true表示要,false表示不要
    private boolean durable = false;

    // 如果当前交换机,没人使用了,就会自动删除
    // 这个属性暂时放在这(后续代码中没有实现,RabbitMQ中实现了)
    private boolean autoDelete = false;

    // arguments 表示的是创建交换机时指定的一些额外参数
    // 这个属性也暂时放在这(后续代码中没有实现,RabbitMQ中实现了)
    // 为了把这个 arguments 存到数据库中,需要将 arguments 转换为 json 格式的字符串
    private Map<String,Object> arguments = new HashMap<>();


    // 这里的 get set 用于与数据库交互使用
    public String getArguments() {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            // 将 arguments 按照 JSON 格式 转换成 字符串
            return objectMapper.writeValueAsString(arguments);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        // 如果代码抛出异常,返回一个空的 json 字符串
        return "{}";
    }

    public void setArguments(String arguments) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            // 将库中的 arguments 按照 JSON 格式解析,转换成 Map 对象
            this.arguments = objectMapper.readValue(arguments, new TypeReference<HashMap<String,Object>>() {});
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    public void setArguments(Map<String,Object> arguments) {
        this.arguments = arguments;
    }


    // 这里的 get set ,用来更方便的获取/设置 arguments 中的键值对
    // 这一组 getter setter 是在Java内部代码使用的(比如测试的时候)
    public Object getArguments(String key) {
        return arguments.get(key);
    }

    public void setArguments(String key,Object value) {
        arguments.put(key, value);
    }
}

创建 MSGQueue类

MSGQueue类中有哪些属性?
与Exchange类大差不差.
直接贴代码

/**
 * 表示一个存储消息的队列
 * MSG =》Message
 * 消息队列的使用者是消费者
 */
@Data
public class MSGQueue {
    // 表示队列的身份标识
    private String name;

    // 表示队列是否持久化
    private boolean durable = false;

    // true -> 这个队列只能被一个消费者使用,false -> 大家都能使用这个队列
    // 后续代码不实现相关功能
    private boolean exclusive = false;

    // true -> 没人使用后,自动删除,false -> 没人使用,不自动删除
    private boolean autoDelete = false;

    // 表示扩展参数,后续代码没有实现
    private Map<String,Object> arguments = new HashMap<>();


    public String getArguments() {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.writeValueAsString(arguments);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void setArguments(String arguments) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            this.arguments = objectMapper.readValue(arguments, new TypeReference<HashMap<String,Object>>() {});
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
    public void setArguments(Map<String,Object> arguments) {
        this.arguments = arguments;
    }

    public Object getArguments(String key) {

        return arguments.get(key);
    }

    public void setArguments(String key,Object value) {
        arguments.put(key, value);
    }
}

创建 Binding类

/**
 * 表示队列和交换机之间的绑定关系
 */
@Data
public class Binding {
    private String exchangeName;
    private String queueName;
    // 主题交换机的匹配key
    private String bindingKey;
}

创建Message类

Message类,大致可以分为三个部分.

  • 消息自身的属性
  • 消息的正文
  • 消息的持久化存储所需属性

我们新建一个 BasicProperties 类来表示 消息的属性.

/**
 * 这个类表示消息的属性
 */
@Data					// 实现 Serializable 接口是为了后续的序列化操作
public class BasicProperties implements Serializable {
    // 消息的唯一身份标识
    private String messageId;

    // 如果当前交换机是 DIRECT,此时 routingKey 表示要转发的队列名
    // 如果当前交换机是 FANOUT,此时 routingKey 无意义
    // 如果当前交换机是 TOPIC,此时 routingKey 就要和bindingKey进行匹配,匹配成功才转发给对应的消息队列
    private String routingKey;

    // 这个属性表示消息是否要持久化,1表示不持久化,2 表示持久化
    private int deliverMode = 1;
}

持久化存储会在下面讲到,莫慌.

/**
 * 这个类表示一个消息
 */
@Data					// 实现 Serializable 接口是为了后续的序列化操作
public class Message implements Serializable {
    // 消息的属性
    private BasicProperties basicProperties = new BasicProperties();
    // 消息的正文
    private byte[] body;

    // 相当于消息的版本号,主要针对 Message 类有改动后,再去反序列化之前旧的 message时,可能会出现错误
    // 因此引入消息版本号,如果版本号不匹配,就不允许反序列化直接报错,来告知程序猿,后续代码中并未实现该功能
    private static final long serialVersionUid = 1L;



    // 下面的属性是持久化存储需要的属性

    // 消息存储到文件中,使用一下两个偏移量来确定消息在文件中的位置 [offsetBeg,offsetEnd)
    // 这两个属性不需要 序列化 存储到文件中,存储到文件中后位置就固定了,
    // 这两个属性的作用是让 内存 中的 message 能顺利找到 文件 中的 message
    // 被 transient 修饰的属性,不会被 标准库 的 序列化方式 序列化
    private transient long offsetBeg = 0; // 消息数据的开头举例文件开头的位置偏移(字节)
    private transient long offsetEnd = 0; // 消息数据的结尾举例文件开头的位置偏移(字节)


    // 使用这个属性表示该消息在文件中是否是有效信息(逻辑删除)
    // 0x1表示有效,0x0表示无效
    private byte isValid = 0x1;

    // 创建工厂方法,让工厂方法封装 new Message 对象的过程
    // 该方法创建的 Message 对象,会自动生成唯一的MessageId
    public static Message createMessageWithId(String routingKey,BasicProperties basicProperties,byte[] body) {
        Message message = new Message();
        if (basicProperties != null) {
            message.setBasicProperties(basicProperties);
        }
        message.basicProperties.setRoutingKey(routingKey);
        // 此处生成的 MessageId 以 M- 作为前缀
        message.setMessageId("M-" + UUID.randomUUID());
        message.setBody(body);

        // 此处先将 message的核心部分 basicProperties 与 body设置了
        // 而 offsetBeg,offsetEnd,isValid,这些属性是持久化时才设置的
        return message;
    }


    // 直接获取消息id
    public String getMessageId() {
        return basicProperties.getMessageId();
    }
    // 直接更改消息id
    public void setMessageId(String messageId) {
        basicProperties.setMessageId(messageId);
    }
    // 直接获取 消息的key
    public String getRoutingKey() {
        return basicProperties.getRoutingKey();
    }
    // 直接更改 消息的key
    public void setRoutingKey(String routingKey) {
        basicProperties.setRoutingKey(routingKey);
    }
    // 直接获取 消息的是否持久化存储字段
    public int getDeliverMode() {
        return basicProperties.getDeliverMode();
    }
    // 直接修改 消息的是否持久化存储字段
    public void setDeliverMode(int mode) {
        basicProperties.setDeliverMode(mode);
    }
}

在这里插入图片描述

这些核心类就都建好了,下篇文章就来考虑他们的持久化存储与内存存储!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1056678.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常见加密和解密方法介绍。

介绍常见的加密和解密方法。 加密是利用数学方法将明文转化为密文&#xff0c;从而达到保护数据的目的。 通过加密可保证数据的机密性、完整性、鉴别性。 机密性&#xff1a;通过数据加密实现。只允许特定用户访问和阅读信息。 完整性&#xff1a;通过数字加密、散列、数字签名…

【生物信息学】使用皮尔逊相关系数进行相关性分析

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 3. IDE 三、实验内容 0. 导入必要的工具 1. cal_pearson&#xff08;计算皮尔逊相关系数&#xff09; 2. 主程序 a. 实验1&#xff08;较强的正相关关系&#xff09;&#xff1a; b. 实验2&#xff0…

计算机网络学习易错点(持续更新~~~)

目录 概述 1.internet和Internet的区别 2.面向连接和无连接 3.不同的T 4.传输速率和传播速率 5.传播时延和传输时延&#xff08;发送时延&#xff09; 6.语法&#xff0c;语义和同步 一.物理层 1.传输媒体与物理层 2.同步通信和异步通信 3.位同步&#xff08;比特同…

leetCode 53.最大子数和 图解 + 贪心算法/动态规划+优化

53. 最大子数组和 - 力扣&#xff08;LeetCode&#xff09; 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入…

C++面试题准备

文章目录 一、线程1.什么是进程&#xff0c;线程&#xff0c;彼此有什么区别?2.多进程、多线程的优缺点3.什么时候用进程&#xff0c;什么时候用线程4.多进程、多线程同步&#xff08;通讯&#xff09;的方法5.父进程、子进程的关系以及区别6.什么是进程上下文、中断上下文7.一…

FFMPEG 视频类过滤器学习整理

addroi 作用 在视频帧上标记一块感兴趣的区域。 帧数据被原封不动地传递&#xff0c;但元数据被附加到帧&#xff0c;指示可能影响后续编码行为的感兴趣区域。可以通过多次应用过滤器来标记多个区域。 参数 qoffset: 应用在此区域的量化偏移。 参数范围&#xff1a;-1 ~ …

笔记一:odoo透视表和图表

透视表 1、首先在xml文件添加pivot 说明&#xff1a;&#xff08;1&#xff09;根元素pivot中属性&#xff1a; disable_linking&#xff1a;设置为True&#xff0c;删除表格单元格到列表视图的链接 display_quantity&#xff1a;设置为True&#xff0c;默认显示“数量”列 d…

什么是FOSS

FOSS 是指 自由和开放源码软件(Free and Open Source Software)。这并不意味着软件是免费的。它意味着软件的源代码是开放的&#xff0c;任何人都可以自由使用、研究和修改代码。这个原则允许人们像一个社区一样为软件的开发和改进做出贡献。

Axios post请求出现500错误

笔者在编写前端form表单传后端数据的时候&#xff0c;出现了以下问题 一、问题场景 当我用axios发送post请求的时候&#xff0c;出现了500错误 笔者找了很长时间错误&#xff0c;代码没问题&#xff0c;后端接口也没问题&#xff0c;后来发现问题出在实体类上了 当前端post请…

电脑msvcp140丢失报错解决方法,msvcp140.dll重新安装的解决方法

msvcp140.dll丢失可能会导致一些基于Microsoft Visual C 编写的程序和游戏无法正常运行。msvcp140.dll是Microsoft Visual C Redistributable的一个组件&#xff0c;它包含了 C 运行时库&#xff0c;这些库在运行程序时会被加载到内存中。如果该文件丢失或损坏&#xff0c;程序…

计算机视觉——飞桨深度学习实战-深度学习网络模型

深度学习网络模型的整体架构主要数据集、模型组网以及学习优化过程三部分&#xff0c;本章主要围绕着深度学习网络模型的算法架构、常见模型展开了详细介绍&#xff0c;从经典的深度学习网络模型以CNN、RNN为代表&#xff0c;到为了解决显存不足、实时性不够等问题的轻量化网络…

用于图像恢复的即插即用 ADMM:定点收敛和应用(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【MySQL入门到精通-黑马程序员】MySQL基础篇-DML

文章目录 前言一、DML-介绍二、DML-添加数据三、DML-修改数据四、DML-删除数据总结 前言 本专栏文章为观看黑马程序员《MySQL入门到精通》所做笔记&#xff0c;课程地址在这。如有侵权&#xff0c;立即删除。 一、DML-介绍 DML&#xff08;Data Manipulation Language&#xf…

【算法|动态规划No.7】leetcode300. 最长递增子序列

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

【iptables 实战】01 iptables概念

一、iptables和netfilter iptables其实不是真正的防火墙&#xff0c;我们可以把它理解成一个客户端代理&#xff0c;用户通过iptables这个代理&#xff0c;将用户的安全设定执行到对应的”安全框架”中&#xff0c;这个”安全框架”才是真正的防火墙&#xff0c;这个框架的名字…

UE4 自带体积云应用

新建空关卡 点击该选项 全部点击一遍 拖进场景

计算机网络(三):数据链路层

参考引用 计算机网络微课堂-湖科大教书匠计算机网络&#xff08;第7版&#xff09;-谢希仁 1. 数据链路层概述 1.1 数据链路层在网络体系结构中所处的地位 链路 (Link) 就是从一个结点到相邻结点的一段物理线路&#xff0c;而中间没有任何其他的交换结点 数据链路 (Data Link)…

倒计时15天!百度世界2023抢先看

近日消息&#xff0c;在10月17日即将举办的百度世界2023上&#xff0c;百度创始人、董事长兼首席执行官李彦宏将带来主题演讲&#xff0c;“手把手教你做AI原生应用”。 增设社会报名&#xff0c;有机会获得精美伴手礼 目前&#xff0c;百度世界大会已经开放公众参会报名&…

选择和操作元素

上一篇文档我们介绍了DOM元素和DOM的获取&#xff1b;其实除了获取DOM&#xff0c;我们也可以去替换DOM元素中的文本 document.querySelector(.message).textContent "&#x1f389;Correct Number"● 除此之外&#xff0c;我们可以设置那个数字部分 document.que…

【iptables 实战】07 iptables NAT实验

在上一节中&#xff0c;我们将两个网段的机器&#xff0c;通过中间机器的网络转发&#xff0c;能达到互通。再来回顾一下这个网络连接的图 上一节我们在防火墙实验中&#xff0c;设置了主机B的的转发规则&#xff0c;我们先清空主机B的转发规则 [rootlocalhost ~]# iptables…