添加的类有: com.lizhaoblog.base.concurrent.commond.ICommand com.lizhaoblog.base.concurrent.commond.IHandler com.lizhaoblog.base.concurrent.dictionary.IMessageDictionary com.lizhaoblog.base.concurrent.handler.AbstractHandler com.lizhaoblog.base.network.processor.IProcessor com.lizhaoblog.server.biz.constant.CommonValue com.lizhaoblog.server.biz.dictionary.MessageHandlerDictionary com.lizhaoblog.server.biz.handler.TestFirstHandler com.lizhaoblog.server.core.processor.LogicProcessor; 修改的类有 NetworkConsumer 这次改的东西比较多了。 我们一个个来看,我们的主线目标,将消息通过不同的id来找到对应的执行类(handler/control),然后扔到线程池中执行。 这样我们写的话就是2个, 一个将消息放到线程池中执行,一个是消息通过不同的id来找到对应的执行类(handler/control) 所以我们先有一个线程池队列,使用IProcessor,里面只有一个方法process,然后看到实现类LogicProcessor,先是声明了一个具体的线程池变量(ThreadPoolExecutor),里面的方法就是执行线程具体线程(executor.execute(handler);) 线程池要执行的需要是一个线程,这个线程需要我们自己实现,所以我们写一个接口ICommand继承Runnable,然后后面的子类继承于ICommand。 在ICommand中就2个方法,一个是执行操作doAction,一个是runable的run方法。这2个都写着,让子类实现就好。 再看下IHandler,IHandler是ICommand的子类,是我们现在所有handler的接口,因为我们是消息传输,肯定会有message和session,所以就在里面写了get/set方法。 但我们写上多个handler后,其实会发现里面的执行逻辑都是一样的,就是在run里面调用doAction方法。就写了一个AbstractHandler,声明 protected T message; protected V param;,然后再run方法里面调用doAction 后面我们要写handler的话(TestFirstHandler),只要继承AbstractHandler然后实现里面的doAction方法 但我们的消息传输上来,我们不确定要通过哪个handler来执行,这时候就需要一个消息字典来进行区分IMessageDictionary(就像web中使用网址区分url一样),具体实现MessageHandlerDictionary就是管理一个map,然后根据键来获取handler。 可以看下具体代码的实现了
com.lizhaoblog.base.concurrent.commond.ICommand
/*
* Copyright (C), 2015-2018
* FileName: ICommand
* Author: zhao
* Date: 2018/6/25 15:37
* Description: 继承runable接口,可以放在线程池中执行
* History:
*
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.base.concurrent.commond;
/**
* 〈一句话功能简述〉
* 〈继承Runnable接口,可以放在线程池中执行〉
*
* @author zhao
* @date 2018/6/25 15:37
* @since 1.0.0
*/
public interface ICommand extends Runnable {
/**
* 执行具体的方法
*/
void doAction();
/**
* 运行
*/
@Override
default void run() {
doAction();
}
}
com.lizhaoblog.base.concurrent.commond.IHandler
/*
* Copyright (C), 2015-2018
* FileName: IHandler
* Author: zhao
* Date: 2018/6/25 15:35
* Description: 队列执行器
* History:
*
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.base.concurrent.commond;
/**
* 〈一句话功能简述〉
* 〈队列执行器〉
*
* @author zhao
* @date 2018/6/25 15:35
* @since 1.0.0
*/
public interface IHandler extends ICommand {
/**
* 消息
* @return 消息request
*/
T getMessage();
/**
* 设置消息request
* @param message request
*/
void setMessage(T message);
/**
* 参数
* @return 参数
*/
V getParam();
/**
* 设置参数
* @param parm 参数
*/
void setParam(V parm);
}
com.lizhaoblog.base.concurrent.dictionary.IMessageDictionary
/*
* Copyright (C), 2015-2018
* FileName: IMessageDictionary
* Author: zhao
* Date: 2018/6/25 14:51
* Description: 消息字典接口
* History:
*
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.base.concurrent.dictionary;
import com.lizhaoblog.base.concurrent.commond.IHandler;
/**
* 〈一句话功能简述〉
* 〈消息字典接口〉
*
* @author zhao
* @date 2018/6/25 14:51
* @since 1.0.0
*/
public interface IMessageDictionary {
/**
* 注册 id--handle
* @param messageId
* @param handler
*/
void register(int messageId, Class extends IHandler> handler);
/**
* 根据messageId获取handler
* @param messageId
* @return
*/
IHandler getHandlerFromMessageId(Integer messageId);
}
com.lizhaoblog.base.concurrent.handler.AbstractHandler
/*
* Copyright (C), 2015-2018
* FileName: AbstractHandler
* Author: zhao
* Date: 2018/6/25 15:54
* Description: 继承ICommand,将一些通用的处理过程写在里面
* History:
*
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.base.concurrent.handler;
import com.lizhaoblog.base.concurrent.commond.IHandler;
/**
* 〈一句话功能简述〉
* 〈继承ICommand,将一些通用的处理过程写在里面〉
*
* @author zhao
* @date 2018/6/25 15:54
* @since 1.0.0
*/
public abstract class AbstractHandler implements IHandler {
protected T message;
protected V param;
/**
* 执行具体的操作,交由子类实现
*/
@Override
public abstract void doAction();
@Override
public void run() {
doAction();
}
@Override
public T getMessage() {
return message;
}
@Override
public void setMessage(T message) {
this.message = message;
}
@Override
public V getParam() {
return param;
}
@Override
public void setParam(V param) {
this.param = param;
}
}
com.lizhaoblog.base.network.processor.IProcessor
/*
* Copyright (C), 2015-2018
* FileName: IProcessor
* Author: zhao
* Date: 2018/6/25 15:34
* Description: 进程接口
* History:
*
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.base.network.processor;
import com.lizhaoblog.base.concurrent.commond.IHandler;
/**
* 〈一句话功能简述〉
* 〈进程接口〉
*
* @author zhao
* @date 2018/6/25 15:34
* @since 1.0.0
*/
public interface IProcessor {
/**
* 执行具体的指令
* @param handler 具体的执行
*/
void process(IHandler handler);
}
com.lizhaoblog.server.biz.constant.CommonValue
/*
* Copyright (C), 2015-2018
* FileName: CommonValue
* Author: zhao
* Date: 2018/6/25 16:45
* Description: 放置常量
* History:
*
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.server.biz.constant;
/**
* 〈一句话功能简述〉
* 〈放置常量〉
*
* @author zhao
* @date 2018/6/25 16:45
* @since 1.0.0
*/
public class CommonValue {
public static final int CM_MSG_TEST = 10001;
private CommonValue() {
}
}
com.lizhaoblog.server.biz.dictionary.MessageHandlerDictionary
/*
* Copyright (C), 2015-2018
* FileName: MessageHandlerDictionary
* Author: zhao
* Date: 2018/6/25 16:39
* Description: 消息字典绑定
* History:
*
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.server.biz.dictionary;
import com.lizhaoblog.base.concurrent.commond.IHandler;
import com.lizhaoblog.base.concurrent.dictionary.IMessageDictionary;
import com.lizhaoblog.server.biz.constant.CommonValue;
import com.lizhaoblog.server.biz.handler.TestFirstHandler;
import com.lizhaoblog.server.pojo.ServerConfig;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
/**
* 〈一句话功能简述〉
* 〈消息字典绑定〉
*
* @author zhao
* @date 2018/6/25 16:39
* @since 1.0.0
*/
@Component
@Scope("singleton")
public class MessageHandlerDictionary implements IMessageDictionary {
private final Map> idHandleMap = new HashMap<>(10);
@PostConstruct
public void init() {
register(CommonValue.CM_MSG_TEST, TestFirstHandler.class);
}
@Override
public void register(int messageId, Class extends IHandler> handler) {
idHandleMap.put(messageId, handler);
}
@Override
public IHandler getHandlerFromMessageId(Integer messageId) {
Class extends IHandler> clazz = idHandleMap.get(messageId);
if (clazz != null) {
try {
return (IHandler) ServerConfig.getInstance().getApplicationContext().getBean(clazz.getSimpleName());
} catch (Exception e) {
return null;
}
}
return null;
}
}
com.lizhaoblog.server.biz.handler.TestFirstHandler
/*
* Copyright (C), 2015-2018
* FileName: TestFirstHandler
* Author: zhao
* Date: 2018/6/25 16:24
* Description: 用于测试的第一个handler
* History:
*
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.server.biz.handler;
import com.lizhaoblog.base.concurrent.handler.AbstractHandler;
import com.lizhaoblog.base.session.Session;
import com.lizhaoblog.base.session.SessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 〈一句话功能简述〉
* 〈用于测试的第一个handler〉
*
* @author zhao
* @date 2018/6/25 16:24
* @since 1.0.0
*/
@Component("TestFirstHandler")
public class TestFirstHandler extends AbstractHandler {
private static final Logger logger = LoggerFactory.getLogger(TestFirstHandler.class);
@Override
public void doAction() {
// logger.info("TestFirstHandler doAction " + this);
logger.info("服务器收到的数据内容:data=" + message);
String result = "小李,我是服务器,我收到你的信息了。";
SessionManager.getInstance().sendMessage(param, result);
}
}
com.lizhaoblog.server.core.processor.LogicProcessor;
/*
* Copyright (C), 2015-2018
* FileName: LogicProcessor
* Author: zhao
* Date: 2018/6/25 16:57
* Description: 具体的消息处理器,进程
* History:
*
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.server.core.processor;
import com.lizhaoblog.base.concurrent.commond.IHandler;
import com.lizhaoblog.base.network.processor.IProcessor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 〈一句话功能简述〉
* 〈具体的消息处理器,进程〉
*
* @author zhao
* @date 2018/6/25 16:57
* @since 1.0.0
*/
public class LogicProcessor implements IProcessor {
private ExecutorService executor = new ThreadPoolExecutor(8, 8, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(100000), new ThreadPoolExecutor.CallerRunsPolicy());
@Override
public void process(IHandler handler) {
this.executor.execute(handler);
}
}
NetworkConsumer
/*
* Copyright (C), 2015-2018
* FileName: INetworkConsumer
* Author: zhao
* Date: 2018/6/23 21:06
* Description: 网络消息处理器
* History:
*
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.server.core.customer;
import com.lizhaoblog.base.concurrent.commond.IHandler;
import com.lizhaoblog.base.network.processor.IProcessor;
import com.lizhaoblog.base.concurrent.dictionary.IMessageDictionary;
import com.lizhaoblog.base.constant.ConstantValue;
import com.lizhaoblog.base.network.customer.INetworkConsumer;
import com.lizhaoblog.base.session.Session;
import com.lizhaoblog.base.session.SessionManager;
import com.lizhaoblog.server.biz.constant.CommonValue;
import com.lizhaoblog.server.core.processor.LogicProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import io.netty.channel.Channel;
/**
* 〈一句话功能简述〉
* 〈网络消息处理器,实现类〉
*
* @author zhao
* @date 2018/6/23 21:09
* @since 1.0.0
*/
@Component
@Scope("singleton")
public class NetworkConsumer implements INetworkConsumer {
private static final Logger logger = LoggerFactory.getLogger(NetworkConsumer.class);
private Map processors = new HashMap<>(10);
@Autowired
private IMessageDictionary messageDictionary;
public void registerProcessor(int queueId, IProcessor processor) {
processors.put(queueId, processor);
}
@PostConstruct
public void init() {
registerProcessor(ConstantValue.QUEUE_LOGIC, new LogicProcessor());
}
@Override
public void consume(String message, Channel channel) {
//获取session,后面需要根据session中的channel进行消息发送
Session session = SessionManager.getInstance().getSessionByChannel(channel);
if (session == null) {
logger.debug("consume session is not found");
return;
}
IHandler handler = messageDictionary.getHandlerFromMessageId(CommonValue.CM_MSG_TEST);
handler.setMessage(message);
handler.setParam(session);
IProcessor processor = processors.get(ConstantValue.QUEUE_LOGIC);
processor.process(handler);
}
}
上面的代码在码云上 https://gitee.com/lizhaoandroid/JgServer 可以加qq群一起探讨Java游戏服务器开发的相关知识 676231564