当前位置: 首页 > article >正文

从零开始手写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<>();

    @Override
    public 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


http://www.kler.cn/a/231752.html

相关文章:

  • 使用 Python 和 Py2Neo 构建 Neo4j 管理脚本
  • python核心语法
  • STL序列式容器之list
  • 【流量分析】常见webshell流量分析
  • Mac 电池没电关机导致时间不同步
  • 基于Java的旅游类小程序开发与优化
  • Redis核心技术与实战【学习笔记】 - 21.Redis实现分布式锁
  • 职业发展 - 一个专注于嵌入式物联网架构设计的攻城狮(转载)
  • npm 上传一个自己的应用(4) 更新自己上传到NPM中的工具版本 并进行内容修改
  • Spring IoC容器(四)容器、环境配置及附加功能
  • Docker进阶篇-CIG重量级监控系统
  • Android13新特性之预测返回手势
  • next项目页面性能调优
  • json、jsonlines格式化显示
  • MySQL温故篇(一)SQL语句基础
  • GEE入门篇|栅格数据集概述(四):其他卫星产品
  • C语言笔试题之实现C库函数 strstr()(设置标志位)
  • k8s弃用docker后使用ctr导入镜像
  • Vue前端框架--Vue工程项目问题总结{脚手架 Vue-cli}
  • 【附代码】NumPy加速库NumExpr(大数据)
  • 【JavaScript】switch 语句
  • Quartus IP 之mif与hex文件创建与使用
  • Hive与Presto中的列转行区别
  • c实现顺序表
  • 解决IntellIJ Idea内存不足
  • 为电子表格嵌入数据库,Excel/WPS一键升级为管理系统