就好像门牌号一样,我们需要把消息路由到对应的楼栋和楼层,总不能像菜鸟一样让大家都来自己找数据吧。
首先这里我们参考了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