Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Openrct2 | 12,465 | 9 hours ago | 1,435 | gpl-3.0 | C++ | |||||
An open source re-implementation of RollerCoaster Tycoon 2 🎢 | ||||||||||
Et | 7,832 | 3 days ago | 60 | mit | C# | |||||
Unity3D Client And C# Server Framework | ||||||||||
Azerothcore Wotlk | 4,906 | 10 hours ago | 1,679 | agpl-3.0 | C++ | |||||
Complete Open Source and Modular solution for MMO | ||||||||||
Cuberite | 4,743 | 14 days ago | 566 | other | C++ | |||||
A lightweight, fast and extensible game server for Minecraft | ||||||||||
Linuxgsm | 3,927 | 4 days ago | 278 | mit | Shell | |||||
The command-line tool for quick, simple deployment and management of Linux dedicated game servers. | ||||||||||
Cellnet | 3,878 | 7 | a year ago | 3 | March 11, 2021 | 8 | mit | Go | ||
High performance, simple, extensible golang open source network library | ||||||||||
Screeps | 2,791 | 4 | 9 | 4 months ago | 166 | November 29, 2023 | 54 | isc | JavaScript | |
A standalone server for programming game Screeps | ||||||||||
Nano | 2,546 | 1 | 18 days ago | 4 | May 06, 2023 | 27 | mit | Go | ||
Lightweight, facility, high performance golang based game server framework | ||||||||||
Impostor | 2,226 | 5 | 4 days ago | 36 | July 16, 2023 | 21 | gpl-3.0 | C# | ||
Impostor - An open source reimplementation of the Among Us Server | ||||||||||
Goworld | 2,151 | a year ago | 8 | June 21, 2021 | 20 | apache-2.0 | Go | |||
Scalable Distributed Game Server Engine with Hot Swapping in Golang |
使用mvn重构项目
JDK 1.8 以上
MySql 5.7 (仅供参考)
Redis 5.0 (仅供参考)
<dependency>
<groupId>com.swingfrog.summer</groupId>
<artifactId>summer</artifactId>
<version>1.1.17</version>
</dependency>
package com.test.summerDemo;
import com.swingfrog.summer.app.Summer;
import com.swingfrog.summer.app.SummerApp;
public class SummerDemoApp implements SummerApp {
@Override
public void init() {
}
@Override
public void start() {
}
@Override
public void stop() {
}
public static void main(String[] args) throws Exception {
Summer.hot(new SummerDemoApp());
}
}
引用外部jar包请放在此目录下,并添加引用。
引用Summer.jar,此jar包依赖SummerServer库。
driverClassName=com.mysql.cj.jdbc.Driver
jdbcUrl=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
username=root
password=123456
poolName=Test
minimumIdle=1
maximumPoolSize=10
connectionTimeout=30000
connectionTestQuery=SELECT 1
asyncCache.coreThread=1
url=127.0.0.1
port=6379
timeout=3000
password=123456
blockWhenExhausted=true
evictionPolicyClassName=org.apache.commons.pool2.impl.DefaultEvictionPolicy
jmxEnabled=true
maxIdle=1
maxTotal=10
maxWaitMillis=30000
testOnBorrow=true
coreThread=1
#服务器集群名称
server.cluster=Gate
#服务器节点名称
server.serverName=gate_s1
#绑定地址
server.address=127.0.0.1
#绑定端口
server.port=8828
#通讯协议
server.protocol=Http
#消息编码
server.charset=UTF-8
#消息密码
server.password=123456
#侦听线程数
server.bossThread=0
#读写线程数
server.workerThread=0
#业务线程数
server.eventThread=0
#消息最大长度 单位字节
server.msgLength=1024000
#心跳时间 单位秒
server.heartSec=40
#请求的间隔时间
server.coldDownMs=10
#是否开启连接白名单
server.allowAddressEnable=true
#白名单允许连接的地址
server.allowAddressList=127.0.0.1,127.0.0.2
#SOCKET: SO_BACKLOG
server.optionSoBacklog=1024
#服务器的其他端口列表
server.minorList=gate_s2
minor.gate_s2.cluster=Gate
minor.gate_s2.serverName=gate_s2
minor.gate_s2.address=127.0.0.1
minor.gate_s2.port=8080
minor.gate_s2.protocol=Http
minor.gate_s2.charset=UTF-8
minor.gate_s2.password=
minor.gate_s2.bossThread=0
minor.gate_s2.workerThread=0
minor.gate_s2.eventThread=0
minor.gate_s2.msgLength=1024000
minor.gate_s2.heartSec=40
minor.gate_s2.coldDownMs=10
minor.gate_s2.allowAddressEnable=false
minor.gate_s2.allowAddressList=
minor.gate_s2.optionSoBacklog=1024
#使用主端口的线程池 (监听线程池, 读写线程池, 业务线程池) 默认为false
minor.gate_s2.useMainServerThreadPool=true
#连接其他服务器的列表
server.clientList=account_s1,account_s2
#其他服务器的集群名称
client.account_s1.cluster=Account
#其他服务器的节点名称
client.account_s1.serverName=account_s1
#连接地址
client.account_s1.address=127.0.0.1
#连接端口
client.account_s1.port=8828
#通讯协议
client.account_s1.protocol=StringLine
#消息编码
client.account_s1.charset=UTF-8
#消息密码
client.account_s1.password=123456
#读写线程数
client.account_s1.workerThread=0
#业务线程数
client.account_s1.eventThread=0
#消息最大长度 单位字节
client.account_s1.msgLength=1024
#心跳时间 单位秒
client.account_s1.heartSec=20
#断线重连间隔时间 单位毫秒
client.account_s1.reconnectMs=100
#远程调用超时时间 单位毫秒
client.account_s1.syncRemoteTimeOutMs=5000
#连接数
client.account_s1.connectNum=1
client.account_s2.cluster=Account
client.account_s2.serverName=account_s2
client.account_s2.address=127.0.0.1
client.account_s2.port=8828
client.account_s2.protocol=StringLine
client.account_s2.charset=UTF-8
client.account_s2.password=123456
client.account_s2.workerThread=0
client.account_s2.eventThread=0
client.account_s2.msgLength=1024
client.account_s2.heartSec=20
client.account_s2.reconnectMs=100
client.account_s2.syncRemoteTimeOutMs=5000
client.account_s2.connectNum=1
在eclipse中可直接运行或调试,启动类为SummerDemoApp.class
在Options中勾选Add directory entries。
注意,不要导出可运行的jar文件,因为会把lib中引用的jar和引用的库打包进jar中,造成jar体积巨大。
java -jar SummerRuntime.jar SummerDemo/SummerDemo.jar com.test.summerDemo.SummerDemoApp
SummerApp由辅助组件和主要组件组成,其中bean、constant、manager、util、exception为辅助组件,dao、service、event、handler、push、remote、task、app为主要组件。
javabean、数据表的实体映射
常量声明
对象管理,使用时在类上方使用注解@Bean
@Bean
public class LoginManager {
private ConcurrentHashMap<Integer, SessionContext> accountIdMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<SessionContext, Integer> sessionContextMap = new ConcurrentHashMap<>();
//省略...
}
工具类
异常信息声明
数据库操作,类需继承BaseDao并使用注解@Dao
@Dao
public class AccountDao extends BaseDao<Account> {
public Account getById(int id) {
return getBean("select * from t_account where id = ?", id);
}
}
public abstract class BaseDao<T> {
protected int update(String sql, Object... args){}
protected Long insertAndGetGeneratedKeys(String sql, Object... args){}
protected T getBean(String sql, Object... args) {}
protected List<T> listBean(String sql, Object... args) {}
protected <E> E getValue(String sql, Object... args) {}
protected <E> List<E> listValue(String sql, Object... args) {}
protected Map<String, Object> getMap(String sql, Object... args) {}
protected List<Map<String, Object>> listMap(String sql, Object... args) {}
protected <E> E getBeanByClass(String sql, Class<E> clazz, Object... args) {}
protected <E> List<E> listBeanByClass(String sql, Class<E> clazz, Object... args) {}
}
业务处理,使用时在类上方使用注解@Service
@Service
public class AccountService {
@Autowired
private AccountDao accountDao;
public Account getAccountById(int accountId) {
return accountDao.getById(accountId);
}
}
事件处理器,使用时在类上方使用注解@EventHandler
在对应方法上方使用注解@BindEvent,参数为监听的事件的名称。也可使用@BindEvent(value = "事件名称", index = 1),index表示同名事件处理器的先后顺序,index小到大,顺序先到后。
如果该方法的返回值不为viod、null,则表示对该事件进行拦截,因此后面的事件处理器便不会收到通知。
@EventHandler
public class FriendEvent {
@BindEvent("登录事件")
public void noticeFriend(int accountId) {}
}
服务器会话回调,类需实现SessionHandler并使用注解@ServerHandler
此组件主要用于网关服务器,可对用户的连接和请求进行拦截或其他处理
@ServerHandler
public class LoginHandler implements SessionHandler {
//是否允许该会话连接服务器 此处可进行黑名单拦截或白名单放行
@Override
public boolean accept(SessionContext sctx) {
return true;
}
//会话连接成功
@Override
public void added(SessionContext sctx) {
}
//会话心跳超时
@Override
public void heartTimeOut(SessionContext sctx) {
}
//会话发来的消息长度大于配置
@Override
public void lengthTooLongMsg(SessionContext sctx) {
}
//是否接收会话发来的消息
@Override
public boolean receive(SessionContext sctx, SessionRequest request) {
return true;
}
//是否接收会话发来的消息 用于protobuf
@Override
public boolean receive(SessionContext ctx, ProtobufRequest request) {
return true;
}
//会话断开连接
@Override
public void removed(SessionContext sctx) {
}
//会话发送重复消息
@Override
public void repetitionMsg(SessionContext sctx) {
}
//会话发送消息次数间隔小于配置
@Override
public void sendTooFastMsg(SessionContext sctx) {
}
//会话发来的消息无法解析
@Override
public void unableParseMsg(SessionContext sctx) {
}
}
推送接口,使用时在类上方使用注解@Push
用于将消息推送给连接本服务器的其他服务器或客户端
@Push
public class DataPush {
public void pushDataToAll(DataPushMsg msg) {
Summer.getServerPush().asyncPushToAll(msg.getRemote(), msg.getMethod(), msg.getData());
}
}
远程调用接口,使用时在类上方使用注解@Remote
SessionContext为调用此接口的会话,此参数可省略。
除了标记@Optional的参数外,皆为必填参数,如有遗漏会抛出异常。
@Remote
public class AccountRemote {
@Autowired
private AccountService accountService;
public Account getAccount(SessionContext sctx, int accountId, @Optional remark) {
return accountService.getAccountById(accountId);
}
}
定时任务,使用时在类上方使用注解@Task
在对应的方法上方添加注解@CronTask、@IntervalTask,即表示该方法为一个任务。
@CronTask("cron 表达式")当时间满足cron表达式时执行该方法
@IntervalTask(1000)每隔1000毫秒执行该方法,或使用@IntervalTask(value = 1000, delay = 2000)2000毫秒后执行该方法,然后每隔1000毫秒执行该方法。
@Task
public class StatTask {
@CronTask("0 0/5 * * * ? ")
public void onlineStatTask() {
}
@IntervalTask(1000)
public void updateXX() {
}
@IntervalTask(value = 1000, delay = 2000)
public void waitAndUpdate() {
}
}
app启动类,此类需实现SummerApp且添加程序入口main方法,并在main方法中调用启动框架。
Summer.hot会在后面提到。
public class SupmersGateApp implements SummerApp {
private static final Logger log = LoggerFactory.getLogger(SupmersGateApp.class);
//框架初始化后回调
@Override
public void init() {
log.info("gate init");
}
//框架启动后回调
@Override
public void start() {
log.info("gate start");
}
//框架停止后回调
@Override
public void stop() {
log.info("gate stop");
}
public static void main(String[] args) throws Exception {
Summer.hot(new SupmersGateApp());
}
}
remote 可调用service、util、manager、constant、bean、exception
push 可调用service、util、manager、constant、bean
handler 可调用service、util、manager、constant、bean
event 可调用service、util、manager、constant、bean
task 可调用service、util、manager、constant、bean、exception
service 可调用dao、service、util、manager、constant、bean、exception
util 可调用util、manager、constant、bean
manager 可调用util、manager、constant、bean
constant 无
bean 无
remote 由远程服务器或客户端调用
push 由远程服务器推送调用
handler 由框架根据会话信息调用
event 由事件驱动器调用
task 由任务处理器调用
注解主要分为两大类,组件类与辅助类。
@Bean、@Dao、@Service、@Remote、@Push、@Task、@ServerHandler、@EventHandler
此类注解只用于类
使用此注解的类,在框架启动时,会自动扫描进容器并实例化常驻于内存中。
@Autowired、@Synchronized、@SingleQueue、@SessionQueue、@Optional、@Transaction、@CronTask、@IntervalTask、@BindEvent
此类注解只用于字段、方法、参数
声明此类为容器中普通组件(manager、other)。
声明此类为数据库操作(dao)。
声明此类为业务处理(service)。
声明此类为远程接口(remote)。
声明此类为推送接口(push)。
声明此类为定时任务(task)。
声明此类为服务器会话回调(handler)。
声明此类为事件处理器(event)。
在使用@Service、@Remote、@Push、@Task、@ServerHandler、@EventHandler这些注解的类中,其字段如果使用此注解,即可实现自动注入,注入的对象由容器提供。
组件中只有@Bean、@Dao、@Service支持被注入。
@Remote
public class AccountRemote {
@Autowired
private AccountService accountService;
@Autowired
private StatService statService;
@Autowired
private ItemService itemService;
@Autowired
private DanService danService;
@Autowired
private PushManager pushManager;
}
在使用@Service、@Remote、@Task、@EventHandler这些注解的类中,其方法如果使用此注解,即可为该方法上分布式锁。当该方法被调用时,会尝试获取锁,一直等到获取成功,执行完方法或抛异常会自动释放锁。
此锁适用于多服务器同步。
@Remote
public class ShopRemote {
@Synchronized("购物锁")
public void buyGoods(int accountId, int goods) {}
}
在使用@Remote注解的类中,其方法如果使用此注解,在多个线程调用此方法是,会排进指定的队列中,依次完成调用。
@Remote
public class StatRemote {
@SingleQueue("队列名称")
public void peopleOnline(int accountId) {}
// 使用 ${arg} arg为方法内参数名称
@SingleQueue("队列名称-${accountId}-${a}")
public void peopleOffline(int accountId, int a) {}
}
在使用@Remote注解的类中,其方法参数如果使用此注解,即视为选填参数。
@Remote
public class AccountRemote {
public Account getAccount(SessionContext sctx, int accountId, @Optional remark) {}
}
在使用@Remote、@Task、@EventHandler这些注解的类中,其方法如果使用此注解,即可开启mysql事务管理,方法执行完则提交事务,如抛出异常则回滚事务。
@Remote
public class FriendRemote {
@Transaction
public void addFriend(int accountId, String name) {}
}
在使用@Task注解的类中,其方法参数如果使用此注解,即视为定时任务。
@CronTask("cron 表达式")
@Task
public class StatTask {
@CronTask("0 0/5 * * * ? ")
public void onlineStatTask() {}
}
在使用@Task注解的类中,其方法参数如果使用此注解,即视为间隔任务。
@IntervalTask(1000) 立即执行并每1000毫秒再执行。
@IntervalTask(value = 1000, delay = 2000) 等待2000毫秒执行并每1000毫秒再执行。
@Task
public class StatTask {
@IntervalTask(1000)
public void updateXX() {}
@IntervalTask(value = 1000, delay = 2000)
public void waitAndUpdate() {}
}
在使用@EventHandler注解的类中,其方法参数如果使用此注解,即为该方法绑定了相应的事件,当有指定的事件发出时,事件驱动就会调用该方法。
@BindEvent("事件名称")
@BindEvent(value = "事件名称", index = 1) index表示同名事件处理器的先后顺序,
index小到大,顺序先到后。
@EventHandler
public class FriendEvent {
@BindEvent("登录事件")
public void noticeFriendOnline(int accountId) {}
@BindEvent(value = "登出事件", index = 1)
public void noticeFriendoffline(int accountId) {}
}
核心方法可在任意地方使用。
Summer框架启动方法
public static void hot(SummerApp app) throws Exception {}
public static void hot(SummerApp app, String projectPackage) throws Exception {}
public static void hot(SummerConfig config) {}
分布式锁
public static void sync(String key, Runnable runnable) {}
队列处理
public static void execute(Object key, Runnable runnable) {}
添加组件到容器
public static void addComponent(Object obj) {}
从容器中移除组件
public static void removeComponent(Object obj) {}
从容器中获取组件
public static <T> T getComponent(Class<?> clazz) {}
从容器中获取组件
public static <T> List<T> listDeclaredComponent(Class<T> clazz) {}
创建代理对象
public static <T> T getProxyInstance(Object target, ProxyMethodInterceptor interceptor) {}
public interface ProxyMethodInterceptor {
Object intercept(Object obj, Method method, Object[] args) throws Throwable;
}
组件注入,为目标对象中使用@Autowired注解的字段,进行对象注入。
public static void autowired(Object obj) {}
获取Redis源,可用于操作Redis。
public static RedisSource getRedisSource() {}
创建间隔任务
public static TaskTrigger getIntervalTask(long interval, long delay, String taskName, TaskJob taskJob) {}
创建定时任务
public static TaskTrigger getCronTask(String cron, String taskName, TaskJob taskJob) {}
开始任务
public static void startTask(TaskTrigger taskTrigger) {}
停止任务
public static void stopTask(TaskTrigger taskTrigger) {}
通过集群名称和服务器节点名称获取连接其他服务器的远程调用接口对象
public static ClientRemote getClientRemote(String cluster, String name) {}
public class ClientRemote {
//异步调用远程接口
public void asyncRemote(String remote, String method, Object data, RemoteCallback remoteCallback) {}
//同步调用远程接口 (如果等待时间超出配置,则抛出异常)
public <T> T syncRemote(String remote, String method, Object data, Type type) {}
}
通过集群名称,随机获取连接其他服务器的远程调用接口对象
public static ClientRemote getRandomClientRemote(String cluster) {}
通过集群名称和服务器节点名称获取连接其他服务器的远程调用接口代理对象
public static <T> T getRemoteInvokeObject(String cluster, String name, Class<?> clazz) {}
通过集群名称和服务器节点名称获取连接其他服务器的远程调用接口代理对象,超时将自动重试直到成功为止
public static <T> T getRemoteInvokeObjectWithRetry(String cluster, String name, Class<?> clazz) {}
通过集群名称,随机获取连接其他服务器的远程调用接口代理对象
public static <T> T getRandomRemoteInvokeObject(String cluster, Class<?> clazz) {}
通过集群名称,随机获取连接其他服务器的远程调用接口代理对象,超时将自动重试直到成功为止
public static <T> T getRandomRemoteInvokeObjectWithRetry(String cluster, Class<?> clazz) {}
@Remote
public class FriendRemote {
@Autowired
private FriendService friendService;
@Transaction
public void addFriend(int accountId, String name) {
this.friendService.addFriend(accountId, name);
}
}
public class AccountServerRemote {
public static FriendRemote getFriendRemote() {
return Summer.getRandomRemoteInvokeObject(ClusterConst.ACCOUNT, FriendRemote.class);
}
}
将账号服务器的jar包引入网关服务器中,即可像调用本地方法一样调用远程接口。
@Remote
public class FriendRemote {
@Autowired
private LoginManager loginManager;
public void addFriend(SessionContext sctx, String name) {
int accountId = loginManager.getAccountId(sctx);
AccountServerRemote.getFriendRemote().addFriend(accountId, name);
}
}
获取服务器推送接口对象
public static ServerPush getServerPush() {}
public class ServerPush {
//异步推送至该集群内所有服务器
public void asyncPushToClusterAllServer(String cluster, String remote, String method, Object data) {}
//同步推送至该集群内所有服务器
public void syncPushToClusterAllServer(String cluster, String remote, String method, Object data) {}
//异步推送至该集群内随机一台服务器
public void asyncPushToClusterRandomServer(String cluster, String remote, String method, Object data) {}
//同步推送至该集群内随机一台服务器
public void syncPushToClusterRandomServer(String cluster, String remote, String method, Object data) {}
//异步推送至该集群中指定的服务器
public void asyncPushToClusterThisServer(String cluster, String serverName, String remote, String method, Object data) {}
//同步推送至该集群中指定的服务器
public void syncPushToClusterThisServer(String cluster, String serverName, String remote, String method, Object data) {}
//异步推送至该会话
public void asyncPushToSessionContext(SessionContext sessionContext, String remote, String method, Object data) {}
//同步推送至该会话
public void syncPushToSessionContext(SessionContext sessionContext, String remote, String method, Object data) {}
//异步推送至部分会话
public void asyncPushToSessionContexts(List<SessionContext> sessionContexts, String remote, String method, Object data) {}
//同步推送至部分会话
public void syncPushToSessionContexts(List<SessionContext> sessionContexts, String remote, String method, Object data) {}
//异步推送至所有会话
public void asyncPushToAll(String remote, String method, Object data) {}
//同步推送至所有会话
public void syncPushToAll(String remote, String method, Object data) {}
}
关闭会话
public static void closeSession(SessionContext sctx) {}
获取服务器业务线程池
public static EventLoopGroup getServerEventLoopGroup() {}
获取会话队列大小
public static int getSessionQueueSize(SessionContext sctx){}
创建错误码异常对象
public static CodeException createCodeException(long code, String msg) {}
public static CodeException createCodeException(CodeMsg msg, Object ...args) {}
创建错误码消息
public static CodeMsg createCodeMsg(long code, String msg) {
获取集群名称
public static String getCluster() {}
获取服务器节点名称
public static String getServerName() {}
同步发送消息事件
public static void syncDispatch(String eventName, Object ...args) {}
异步发送消息事件
public static void asyncDispatch(String eventName, Object ...args) {}
获取Web相关接口
public static WebMgr getWeb() {}
调用异常 invoke error
当调用远程接口出现异常并且非自定义ErrorCode时,就会抛出此异常。
远程接口不存在 remote not exist
远程方法不存在 method not exist
参数错误 parameter error
远程接口受保护 remote was protected
Protobuf不存在 protobuf not exist
public class AccountException {
/**金币不足*/
public static final CodeMsg GOLD_NOT_ENOUGH = Summer.createCodeMsg(101005, "gold not enough, accountId[%s] own[%s] need[%s]");
}
建议只在remote和service中使用
@Service
public class AccountService {
@Autowired
private AccountDao accountDao;
public int gainGold(int accountId, int gainGold) {
int ownGold = accountDao.getGoldByIdForUpdate(accountId);
int gold = ownGold + gainGold;
if (gold < 0) {
throw Summer.createCodeException(AccountException.GOLD_NOT_ENOUGH, accountId, ownGold, gainGold);
} else if (gold > AccountConst.GOLD_MAX) {
gold = AccountConst.GOLD_MAX;
}
accountDao.updateGold(accountId, gold);
return gold;
}
}
{"id": 0, "remote": null, "method": null, "data": {}}
id 由客户端不断递增,由1开始
remote 远程接口 -> 类名
method 远程方法 -> 方法名
data 数据 -> 方法参数名与值
{"code": 0, "id": 0, "remote": null, "method": null, "data": null, "time": 0}
code 错误码,为0标识无异常
id 与客户端请求消息的id一致
remote 请求的远程接口
method 请求的远程方法
data 返回的数据
time 时间戳
{"code": 0, "id": 0, "remote": null, "method": null, "data": null, "time": 0}
code 为0
id 为0,可根据id是否为0来判断是否是推送消息
remote 推送接口
method 推送方法
data 推送的数据
time 时间戳
proto名称格式: 类名_Req_协议消息ID
例如: HeartBeat_Req_0
proto名称格式: 类名_Resp_协议消息ID
例如: HearBeat_Resp_0
proto名称格式: 类名_Push_协议消息ID
例如: Test_Push_100
本协议支持加解密,支持服务器之间使用。消息格式为字符串,在字符串末尾加入\r\n,因此通过判断分隔符\r\n来区分消息。
#通讯协议
server.protocol=StringLine
本协议支持加解密,基于WebSocket协议。消息格式为二进制,数据包分为包头和包体,包头占四个字节,用来表示包体的长度。
#通讯协议
server.protocol=WebSocket
本协议支持加解密,支持服务器之间使用。消息格式为二进制,数据包分为包头和包体,包头占四个字节,用来表示包体的长度。
#通讯协议
server.protocol=LengthField
本协议不支持加解密,基于WebSocket协议。消息格式为Protobuf,数据包分为包头和包体,包头占四个字节,用来表示包体的长度。包体前四个字节为协议消息ID,后面的字节为协议内容。
#通讯协议
server.protocol=WebSocket-Protobuf
本协议不支持加解密,不支持服务器之间使用。消息格式为Protobuf,数据包分为包头和包体,包头占四个字节,用来表示包体的长度。
#通讯协议
server.protocol=LengthField-Protobuf
本协议支持加解密,基于WebSocket协议。消息格式为二进制,数据包只包含包体。
#通讯协议
server.protocol=WebSocket-Standard
本协议不支持加解密,基于WebSocket协议。消息格式为Protobuf,数据包只包含包体,包体前四个字节为协议消息ID,后面的字节为协议内容。
#通讯协议
server.protocol=WebSocket-Protobuf-Standard
本协议不支持加解密,基于Http协议。
@Remote
public class TestRemote {
public void test(String msg) {
}
}
//地址:端口/远程接口_远程方法?请求数据
http://127.0.0.1:8080/TestRemote_test?msg=hello
#通讯协议
server.protocol=Http
byte[] bytes = new byte[0];
String pass = "123456"; //密码由配置文件配置
int index = bytes.length % 10;
for (int i = 0; i < bytes.length; i++) {
if (index >= pass.length)
index = 0;
int res = bytes[i] ^ pass[index];
bytes[i] = (byte)res;
index++;
}
byte[] bytes = new byte[0];
String pass = "123456"; //密码由配置文件配置
int index = bytes.length % 10;
for (int i = 0; i < bytes.length; i++) {
if (index >= pass.length)
index = 0;
int res = bytes[i] ^ pass[index];
if (res != 10 && res != 13)
bytes[i] = (byte)res;
index++;
}
public class WebMgr {
//重新加载模板
public void reloadTemplate() {}
//获取模板
public Template getTemplate(String templateName) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {}
//获取Web内容文件路径
public String getWebContentPath() {}
//设置Web内容文件路径
public void setWebContentPath(String webContentPath) {}
//获取模板文件路径
public String getTemplatePath() {}
//设置模板文件路径
public void setTemplatePath(String templatePath) {}
//获取内部视图渲染工厂
public InteriorViewFactory getInteriorViewFactory() {}
//设置内部视图渲染工厂
public void setInteriorViewFactory(InteriorViewFactory interiorViewFactory) {}
//获取主页路径
public String getIndex() {}
//设置主页路径
public void setIndex(String index) {}
//获取图标路径
public String getFavicon() {}
//设置图标路径
public void setFavicon(String favicon) {}
}
如需自定义空白视图或错误视图,只需继承此类覆盖相应的方法。
public class InteriorViewFactory {
//空白视图
public BlankView createBlankView() {}
//错误视图
public ErrorView createErrorView(int status, long code, String msg) {}
//错误视图
public ErrorView createErrorView(int status, String msg) {}
}
文字视图
new TextView(String text);
JSON视图
new JSONView(JSON json);
文件视图
new FileView(String fileName);
模型视图
ModelView model = new ModelView(String view);
model.put(String key, Object value);
view 模板地址
key 键
value 值
空白视图
new BlankView();
错误视图
new ErrorView(int status, long code, String msg);
new ErrorView(int status, String msg);
status Http状态
code 错误码
msg 错误消息
没有Web视图 not web view
@Remote
public class UserRemote {
public JSONView add(String name, Integer age, @Optional remark) {
JSONObject json = new JSONObject();
json.put("flag", true);
return new JSONView(json);
}
}
http://127.0.0.1:8080/UserRemote_add?name=toke&age=22 //remark为选填
<form action="http://127.0.0.1:8080/UserRemote_add" method="post">
<input type="text" name="name"/>;
<input type="text" name="age"/>;
<input type="text" name="remark"/>;
<input class="button" type="submit"/>
</form>
@Remote
public class FileRemote {
public void upload(WebFileUpload photo) {
photo.saveToFile("photos/");
}
}
<form action="http://127.0.0.1:8080/FileRemote_upload" method="post" enctype="multipart/form-data">
<input type="file" name="photo"/>;
<input class="button" type="submit"/>
</form>
public class WebFileUpload {
//获取文件名
public String getFileName() {}
//获取数据
public ByteBuf getByteBuf() {}
//保存到指定路径
public void saveToFile(String path) throws IOException {}
}
通过Summer.hot启动框架。
初始化 -> 启动 -> 运行时 -> 停止
停止需要外部进行操作 kill -2 pid、kill -15 pid
与会话保存心跳联系,心跳超时会通过handler通知。
与其他服务器保存心跳联系,心跳超时后断线会自动重连。
两种方式触发业务处理,主动与被动。
主动,通过外部调用远程接口remote或会话的行为触发。
被动,通过内部任务处理器执行task触发。
停止一切
随机远程调用和随机推送都是通过轮询实现
public Client getClientWithNext() {
int size = clientList.size();
if (size == 0) {
return null;
}
if (size == 1) {
return clientList.get(0);
}
int n = next.getAndIncrement();
n = Math.abs(n);
n = n % size;
return clientList.get(n);
}
public class RedisSource {
//通过key获取value
public String get(String key) {}
//设置key、value
public String put(String key, String value) {}
//设置key、value,返回是否成功
public boolean putAndSuccess(String key, String value) {}
//设置key、value,key过期时间
public String putWithTime(String key, int seconds, String value) {}
//设置key过期时间
public boolean setExpireTime(String key, int seconds) {}
//取消key过期时间
public boolean delExpireTime(String key) {}
//获取key剩余时间
public long getRemainTime(String key) {}
//判断key是否存在
public boolean exists(String key) {}
//移除key
public boolean remove(String key) {}
//获取key的类型
public String getType(String key) {}
//获取map
public RedisMap getMap(String key) {}
//获取list
public RedisList getList(String key) {}
//获取set
public RedisSet getSet(String key) {}
//获取deque
public RedisDeque getDeque(String key) {}
//清除redis
public void clear() {}
}
封装了Redis的Hash
public class RedisMap implements Map<String, String> {}
封装了Redis的List
public class RedisList extends RedisCollection implements List<String> {}
封装了Redis的Set
public class RedisSet implements Set<String> {}
封装了Redis的List
public class RedisDeque extends RedisCollection implements Deque<String> {}
public abstract class RedisCollection implements Collection<String> {}