从零开始手写mmo游戏从框架到爆炸(六)— 消息处理工厂
就好像门牌号一样,我们需要把消息路由到对应的楼栋和楼层,总不能像菜鸟一样让大家都来自己找数据吧。
首先这里我们参考了rabbitmq中的topic与tag模型,topic对应类,tag对应方法。
新增一个模块,专门记录路由eternity-command

ServerTag.java
public interface ServerTag {/**** 打招呼*/int TAG_HELLO_HI = 1;}
ServerTopic.java
public interface ServerTopic {/**** 问候*/int TOPIC_HELLO = 1;}
然后再core中引入这个模块,同时增加反射依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.reflections</groupId><artifactId>reflections</artifactId><version>0.9.10</version></dependency><dependency><groupId>com.loveprogrammer</groupId><artifactId>eternity-common</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.loveprogrammer</groupId><artifactId>eternity-command</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>
在core中增加一个文件夹

创建两个注解:
TagListener
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.METHOD;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TagListener {/*** 订阅的tag*/int tag() default 0;/*** 请求方消息类型*/Class<?> messageClass() default Object.class;}
TopicListener
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TopicListener {/*** 订阅的主题*/int topic() default 0;
}
接口IHandler
public interface IHandler {}
抽象实现类BaseHandler
public abstract class BaseHandler implements IHandler{}
hello实现类
import com.loveprogrammer.base.network.command.BaseHandler;
import com.loveprogrammer.base.network.command.HandlerFactory;
import com.loveprogrammer.base.network.command.anotation.TagListener;
import com.loveprogrammer.base.network.command.anotation.TopicListener;
import com.loveprogrammer.command.server.ServerTag;
import com.loveprogrammer.command.server.ServerTopic;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;/*** @ClassName HelloHandler* @Description 测试handler* @Author admin* @Date 2024/2/5 15:49* @Version 1.0*/
@Component
@TopicListener(topic = ServerTopic.TOPIC_HELLO)
public class HelloHandler extends BaseHandler {public static final Logger log = LoggerFactory.getLogger(HelloHandler.class);@TagListener(tag = ServerTag.TAG_HELLO_HI,messageClass = String.class)public void sayHi(Channel channel, String msg){log.info("say hi");}
}
创建监听器工厂 HandlerFactory
import com.loveprogrammer.base.network.command.anotation.TopicListener;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*** @ClassName HandlerFactory* @Description 监听器工厂* @Author admin* @Date 2024/2/5 11:21* @Version 1.0*/
@Component
public class HandlerFactory implements CommandLineRunner {public static final Logger log = LoggerFactory.getLogger(HandlerFactory.class);public Map<Integer, Class> handlerMap = new HashMap<>();@Overridepublic void run(String... args) throws Exception {// 找到所有实现类Reflections reflections = new Reflections("com.loveprogrammer.base.network.command.handler");// 获取在指定包扫描的目录所有的实现类Set<Class<? extends BaseHandler>> classes = reflections.getSubTypesOf(BaseHandler.class);for (Class<? extends IHandler > aClass : classes) {try {TopicListener listeners = aClass.getAnnotation(TopicListener.class);Integer topic = listeners.topic();handlerMap.put(topic, aClass);log.info("初始化消息监听器成功 {}",aClass.getName());} catch (Exception e) {log.error("初始化" + aClass.getName() + "消息监听器失败",e);}}}
}
启动server,查看监听器是否初始化成功。
2024-02-05 16:09:33.860 INFO 14144 --- [ main] c.l.base.network.command.HandlerFactory : 初始化消息监听器成功 com.loveprogrammer.base.network.command.handler.HelloHandler
(♥◠‿◠)ノ゙ springboot启动成功 ლ(´ڡ`ლ)゙
上一篇:从零开始手写mmo游戏从框架到爆炸(五)— 集成springboot-CSDN博客
全部源码详见:
gitee : eternity-online: 多人在线mmo游戏 - Gitee.com
分支:step-06
相关文章:
从零开始手写mmo游戏从框架到爆炸(六)— 消息处理工厂
就好像门牌号一样,我们需要把消息路由到对应的楼栋和楼层,总不能像菜鸟一样让大家都来自己找数据吧。 首先这里我们参考了rabbitmq中的topic与tag模型,topic对应类,tag对应方法。 新增一个模块,专门记录路由eternity-…...
Go基础学习笔记-知识点
学习笔记记录了我在学习官方文档过程中记的要点,可以参考学习。 go build *.go 文件 编译 go run *.go 执行 go mod init 生成依赖管理文件 gofmt -w *.go 格式换名称的大小写用来控制方法的可见域主方法及包命名规范 package main //注意package的命名࿰…...
jvm几个常见面试题整理
1. Full GC触发机制有如下5种情况。 (1)调用System.gc()时,系统建议执行Full GC,但是不必然执行。(2)老年代空间不足。(3)方法区空间不足。(4)老年代的最大可用连续空间小于历次晋升到老年代对象的平均大小就会进行Full GC。(5)由Eden区、S0(From)区向S…...
ReentrantLock 和 公平锁
ReentrantLock 和 公平锁 一、基本介绍 ReentrantLock(重入锁) 是一个独占式锁,具有和synchronize的监视器锁基本相同的行为和语意。但和synchronized相比,它更加的灵活、强大、增加了轮询、超时、中断等高级功能以及可以创建公平和非公平锁。Reentran…...
使用Postman做API自动化测试
Postman最基本的功能用来重放请求,并且配合良好的response格式化工具。 高级点的用法可以使用Postman生成各个语言的脚本,还可以抓包,认证,传输文件。 仅仅做到这些还不能够满足一个系统的开发,或者说过于琐碎&#…...
入门指南|Chat GPT 的兴起:它如何改变数字营销格局?
随着数字营销的不断发展,支持数字营销的技术也在不断发展。OpenAI 的 ChatGPT 是一项备受关注的突破性工具。凭借其先进的自然语言处理能力,ChatGPT 已被证明是全球营销人员的宝贵资产。在这份入门指南中,我们将探讨Chat GPT对数字营销专家及…...
【C#】.net core 6.0 创建默认Web应用,以及默认结构讲解,适合初学者
欢迎来到《小5讲堂》 大家好,我是全栈小5。 这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握。…...
Linux中的numactl命令指南
假设我们想控制线程如何被分配到处理器核心,或者选择我们想分配数据的位置,那么numactl命令就适合此类任务。在这篇文章中,我们讨论了如何使用numactl命令执行此类操作。 目录: 介绍语法命令总结参考文献 简介 现代处理器采用…...
AD域国产替代方案,助力某金融企业麒麟信创电脑实现“真替真用”
近期收到不少企业客户反馈采购的信创PC电脑用不起来,影响信创改造的进度。例如,某金融企业积极响应国产化信创替代战略,购置了一批麒麟操作系统电脑。分发使用中发现了如下问题: • 当前麒麟操作系统电脑无法做到统一身份认证&…...
抽象springBoot报错
Failed to configure a DataSource: url attribute is not specified and no embedded datasource could be configured. 中文翻译:无法配置DataSource:未指定“url”属性,并且无法配置嵌入数据源。 DataSource 翻译:数据源 得…...
Linux的打包压缩与解压缩---tar、xz、zip、unzip
最近突然用到了许久不用的压缩解压缩命令,真的陌生, 哈哈,记录一下,后续就不用搜索了。 tar的打包 tar -cvf 压缩有的文件名称 需要压缩的文件或文件夹tar -cvf virtualbox.tar virtualbox/ tar -zcvf virtualbox.tar virtualbo…...
在angular12中proxy.conf.json中配置详解
一、proxy.conf.json文件的目录 二、proxy.conf.json文件中的配置 "/xxx/api": {"target": "地址/api","secure": false,"logLevel": "debug","changeOrigin": true,"pathRewrite": {"…...
PyTorch 中音频信号处理库torchaudio的详细介绍
torchaudio 是 PyTorch 深度学习框架的一部分,是 PyTorch 中处理音频信号的库,专门用于处理和分析音频数据。它提供了丰富的音频信号处理工具、特征提取功能以及与深度学习模型结合的接口,使得在 PyTorch 中进行音频相关的机器学习和深度学习…...
OpenAI研究揭示:ChatGPT对生物武器制造影响有限
### OpenAI研究揭示:ChatGPT对生物武器制造影响有限 在最近的一项引人注目的研究中,OpenAI探索了其旗舰人工智能产品GPT-4在辅助制造生物武器方面的潜力。尽管公众对人工智能可能带来的潜在风险表示担忧,但OpenAI的发现却意味着这种担忧可能…...
IntelliJ IDEA 2023.3发布,AI 助手出世,新特性杀麻了!!
目录 关键亮点 对 Java 21 功能的完全支持 调试器中的 Run to Cursor(运行到光标)嵌入选项 带有编辑操作的浮动工具栏 用户体验优化 Default(默认)工具窗口布局选项 默认颜色编码编辑器标签页 适用于 macOS 的新产品图标 Speed Sear…...
async 与 await(JavaScript)
目录捏 前言一、async二、await三、使用方法总结 前言 async / await 是 ES2017(ES8) 提出的基于 Promise 解决异步的最终方案。上一篇文章介绍了 回调地狱 与 Promise(JavaScript),因为 Promise 的编程模型依然充斥着大量的 then 方法&#…...
GPT-1, GPT-2, GPT-3, GPT-3.5, GPT-4论文内容解读
目录 1 ChatGPT概述1.1 what is chatGPT1.2 How does ChatGPT work1.3 The applications of ChatGPT1.3 The limitations of ChatGPT 2 算法原理2.1 GPT-12.1.1 Unsupervised pre-training2.1.2 Supervised fine-tuning2.1.3 语料2.1.4 分析 2.2 GPT-22.3 GPT-32.4 InstructGPT…...
第62讲商品搜索动态实现以及性能优化
商品搜索后端动态获取数据 后端动态获取数据: /*** 商品搜索* param q* return*/GetMapping("/search")public R search(String q){List<Product> productList productService.list(new QueryWrapper<Product>().like("name", q)…...
我的PyTorch模型比内存还大,怎么训练呀?
原文:我的PyTorch模型比内存还大,怎么训练呀? - 知乎 看了一篇比较老(21年4月文章)的不大可能训练优化方案,保存起来以后研究一下。 随着深度学习的飞速发展,模型越来越臃肿,哦不&a…...
HTTP协议笔记
HTTP协议笔记 参考: (建议精读)HTTP灵魂之问,巩固你的 HTTP 知识体系 《透视 HTTP 协议》——chrono 目录: 1、说说你对HTTP的了解吧。 1. HTTP状态码。 2. HTTP请求头和响应头,其中包括cookie、跨域响…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
2.3 物理层设备
在这个视频中,我们要学习工作在物理层的两种网络设备,分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间,需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质,假设A节点要给…...
