Skip to content

solution.xml 参考

本文是 solution.xml 的完整语法参考——列出所有元素及其属性、类型系统、跨语言映射,供写代码时随查随用。概念讲解见 定义数据,生成的 Bean 与 Table 细节见 Bean 数据模型Table 存储接口

solution.xml 描述了应用的数据模型(Bean)、存储(Table)、网络协议(Protocol/Rpc)和代码生成目标(Project/Service)。顶层元素结构如下:

<?xml version="1.0" encoding="UTF-8"?>
<solution name="..." ModuleIdAllowRanges="...">
<import file="..."/> <!-- 引入其他 solution 文件 -->
<module name="..." id="..."> <!-- 逻辑模块,可嵌套 -->
<bean name="..."> ... </bean>
<beankey name="..."> ... </beankey>
<table name="..." key="..." value="..."/>
<rpc name="..." .../>
<protocol name="..." .../>
<enum name="..." value="..."/>
</module>
<external bean="..."/> <!-- 引用手写 Bean -->
<externalkey beankey="..."/>
<project name="..." ...> <!-- 代码生成目标 -->
<service name="..." ...> <module ref="..."/> </service>
<ModuleStartOrder> ... </ModuleStartOrder>
</project>
</solution>

属性必填说明
name顶层命名空间。生成的 Java 类会落在 Zeze.<name>.<module>
ModuleIdAllowRanges模块 id 的合法范围。支持区间(1-1000)、离散值(100)、逗号分隔混合(1-1000,2000)。多个 solution 文件合并后范围不可重叠
<solution name="Game" ModuleIdAllowRanges="1-1000">
属性说明
file要引入的 solution 文件路径
  • 可以相互 import,框架负责解析循环依赖。
  • 适合把大型数据模型拆分到多个文件,按模块/团队管理。
<import file="role.xml"/>
<import file="../common/types.xml"/>

模块是逻辑分组,id 全局唯一。可嵌套,内部可包含 bean/table/rpc/protocol/enum。

属性必填说明
name模块名,用作生成代码的命名空间
id全局唯一模块 id,必须在 ModuleIdAllowRanges 范围内
hot热更新相关标记
DefaultTransactionLevel该模块默认事务级别(覆盖程序默认)
UseData控制是否生成 Data 类
<module name="role" id="1">
<module name="bag" id="2"> <!-- 嵌套模块 -->
...
</module>
</module>

Bean 是结构化数据的基本单元,自动参与事务。详见 Bean 数据模型

属性必填说明
nameBean 名
version版本标记字段名(类型 long,修改时自动递增)
equalstrue 时生成 equals / hashCode
interface指定生成的 Bean 实现的接口
UseData"true" 生成 Data 类;"only" 只生成 Data 类
MappingClass生成关系映射类(用于关系型数据库映射)
kind特殊类型,如 "rocks"
comment注释,生成到代码注释里
<bean name="Player" version="ver" equals="true">
<variable id="1" name="name" type="string"/>
<variable id="2" name="level" type="int"/>
</bean>

语法与 <bean> 相同,但用作 Table 的复合主键。可以为空(空 key 作占位):

<beankey name="RoleIdServerKey">
<variable id="1" name="roleId" type="long"/>
<variable id="2" name="serverId" type="int"/>
</beankey>
<!-- 空 beankey -->
<beankey name="EmptyKey"/>

用作 Table 的 key 时,beankey 生成的类必须实现 Comparable

属性必填说明
idBean 内唯一正整数(≤ 4095)。用于序列化和版本兼容,删除后不可复用
name字段名
type字段类型,见下方类型表
keymap/set 时声明键类型
valuemap/list/set/dynamic 时声明值类型或 bean 名
default默认值
AllowNegative允许负数
transienttrue 时不持久化
javaType特化集合实现类型
<variable id="1" name="level" type="int" default="1"/>
<variable id="2" name="friends" type="set" value="long"/>
<variable id="3" name="scores" type="map" key="int" value="float"/>
<!-- 方括号简写 -->
<variable id="4" name="names" type="list[string]"/>

类型Java 对应说明
boolboolean布尔
bytebyte8 位有符号整数
shortshort16 位有符号整数
intint32 位有符号整数
longlong64 位有符号整数
floatfloat32 位浮点
doubledouble64 位浮点
stringStringUTF-8 字符串
binaryZeze.Net.Binary字节序列(Java/C# 均映射为 Zeze.Net.Binary
decimalBigDecimal高精度十进制
vector2Vector2两 float
vector2intVector2Int两 int
vector3Vector3三 float
vector3intVector3Int三 int
vector4Vector4四 float
quaternionQuaternion四元数
类型说明方括号简写
list有序列表,元素可 Beanlist[long]list[Item]
set无序集合set[long]
map键值映射map[int,float]map[int,Item]
array数组
gtable

集合的元素本身可以是 Bean,支持任意嵌套。

类型说明
Bean名嵌套引用其他 Bean
dynamic动态 Bean,运行时多态,见下节
beankey名引用复合键

省去装箱开销,生成更高效的具体实现:

javaType用途
IntList / LongList / FloatList基本类型 List(没有 DoubleList
Vector2List / Vector3List / Vector4Listfloat 向量 List
Vector2IntList / Vector3IntListint 向量 List
IntHashSet / LongHashSet基本 Set
IntHashMap<V> / LongHashMap<V>基本类型 Map
<variable id="1" name="ids" type="list" value="int" javaType="IntList"/>

用一个 variable 持有多种 Bean 类型,运行时通过 typeId() 区分。用 <value> 列出所有可能类型:

<bean name="Pet"/>
<bean name="Mount"/>
<bean name="Role">
<variable id="1" name="partner" type="dynamic">
<value bean="Pet"/>
<value bean="Mount"/>
</variable>
</bean>
属性 / 用法说明
<value bean="..."/>列出可能持有的 Bean
完全限定名可跨模块引用,如 <value bean="Game.Item.BHorseExtra"/>
显式 typeId<value bean="demo.Bean1:1"/> 指定 typeId 为 1
简写type="dynamic:BSimple" 等价于只列一个 BSimple
自定义工厂实现 GetSpecialTypeIdFromBean / CreateBeanFromSpecialTypeId / CreateDataFromSpecialTypeId

dynamic 不支持嵌套(dynamic 字段里再套 dynamic 不允许)。未设置时用 EmptyBean(typeId=0)表示。详见 Bean 数据模型


同一份 XML 生成的多语言客户端,类型对应关系如下:

XML 类型JavaC#LuaTypeScript
boolbooleanboolbooleanboolean
bytebytesbytenumbernumber
shortshortshortnumbernumber
intintintnumbernumber
longlonglongnumbernumber / bigint
floatfloatfloatnumbernumber
doubledoubledoublenumbernumber
stringStringstringstringstring
binaryZeze.Net.BinaryZeze.Net.BinarystringUint8Array
XML 类型JavaC#LuaTypeScript
mapHashMapDictionarytableMapCollMap2/PMap2
listArrayListListtableArrayCollList2/PList2
setHashSetHashSettableSetCollSet2/PSet2
dynamicDynamicBeanDynamicBeantableDynamicBean

可定义在 bean / rpc / module 内,生成代码里得到对应常量。常用于声明错误码。

属性必填说明
name常量名
value
comment注释
<module name="role" id="1">
<enum name="ERR_COIN_NOT_ENOUGH" value="1" comment="金币不足"/>
<enum name="ERR_NOT_FOUND" value="2" comment="玩家不存在"/>
</module>

模块级错误码编码为 (moduleId << 32) | errorCode,详见 事务系统


声明后生成 TableXxx<K, V> 子类,语义等价 Map<K,V>。详见 Table 存储接口

属性必填说明
name表名,生成类名前缀
key基本类型或 beankey(必须 Comparable
value必须是 bean
memorytrue 纯内存表,不持久化
autokey"true" 自动键;"random" 随机键
RelationalMapping关系映射
suffix表名后缀模板,如 _@AppMainVersion_@ServerId
gen指定生成的 project
kind特殊类型
noSchematrue 时不使用 Schema 校验
comment注释
<table name="tPlayer" key="long" value="Player"/>
<table name="tMail" key="long" value="Mail" suffix="_@ServerId"/>
<table name="tCounter" key="long" value="Counter" memory="true"/>

属性必填说明
nameRpc 名
argument参数 Bean
result结果 Bean。若 result 含 resultCode(long)字段会被特殊处理,0 为正常
handle处理方,见下方 handle 表
base基类
TransactionLevel事务级别
NoProcedure不在存储过程中执行
CriticalLevel重要级别
UseData控制是否生成 Data 类
comment注释
<rpc name="Login" argument="LoginArg" result="LoginRes" handle="server"/>
属性必填说明
name协议名。建议加 C(客户端发服务端)/ S(服务端发客户端)前缀
argument参数 Bean
handle处理方
TransactionLevel事务级别
NoProcedure不在存储过程中执行
CriticalLevel重要级别
UseData控制 Data 类生成
comment注释
<protocol name="CHeartbeat" argument="EmptyBean" handle="server"/>
<protocol name="SCoinChanged" argument="CoinChanged" handle="client"/>

决定由谁处理该协议,可逗号组合:

说明
server服务端处理
client客户端处理
serverscript服务端脚本处理
clientscript客户端脚本处理
servletHTTP 服务端点处理(用于 <servlet>
<rpc name="Echo" argument="EchoArg" result="EchoRes" handle="server,client"/>

一个 <project> 对应一个进程(生成目标),定义代码生成参数。

属性必填说明
nameproject 名
GenDir生成代码输出目录
SrcDir手写源码目录
platform目标平台(见下方取值表)
hot热更新相关
MappingClass生成关系映射类
ClientScript客户端脚本配置
GenTables指定生成哪些表
<project name="GameServer" GenDir="gen" SrcDir="src" platform="java">
...
</project>

platform 取值(生成器实际支持的活跃值):

platform说明
java服务端 Java 代码
conf+csC# 客户端配置 + 代码(含 Table 等)
conf+cs+netC# 客户端配置 + 代码 + 网络层(联网需要)
cxxC++ 客户端
tsTypeScript 客户端
cxx+ts同时生成 C++ 与 TypeScript
luaclientLua 客户端脚本(宿主嵌入 C++/C#)
pythonPython 客户端

⚠️ 注意:单独的 cscs+luaclientcs+ts 这三个取值已被废弃(源码中已注释掉)。需要 C# 客户端请用 conf+csconf+cs+net

project 内定义网络服务,用 <module ref> 引用模块。

属性必填说明
name服务名
handle处理方
base基服务类(如 main
<service name="GameServer" handle="server" base="main">
<module ref="role"/>
<module ref="role.bag"/>
</service>

控制 project 内模块的启动顺序:

<project name="GameServer" ...>
<ModuleStartOrder>
<module ref="role"/>
<module ref="bag"/>
</ModuleStartOrder>
</project>

引用由 Java 代码直接编写(非生成)的 Bean 或 beankey,用完全限定名:

<external bean="Game.Item.BHandwrittenExtra"/>
<externalkey beankey="Game.Role.HandKey"/>

声明 HTTP 服务端点,name 同时作为 URL 路径。

属性必填说明
name名称,同时作 URL 路径
TransactionLevel事务级别
<servlet name="/api/health" TransactionLevel="None"/>

在一个模块里引用另一个模块(甚至另一个 solution 文件)的 Bean / beankey / Table 时,使用完全限定名

格式说明
解决方案名.模块名.Bean名跨 solution + 模块引用
解决方案名.Bean名Bean 在 solution 直接子节点时
<!-- 在 role 模块引用 Game.Item 模块的 Bean -->
<variable id="1" name="horse" type="dynamic">
<value bean="Game.Item.BHorseExtra"/>
</variable>

下面是一个覆盖主要元素的完整示例:

<?xml version="1.0" encoding="UTF-8"?>
<solution name="Game" ModuleIdAllowRanges="1-1000">
<!-- 引入公共类型 -->
<import file="common/types.xml"/>
<!-- 角色模块 -->
<module name="role" id="1" DefaultTransactionLevel="Serializable">
<!-- 玩家数据(Table 的 value) -->
<bean name="Player" version="ver" equals="true">
<variable id="1" name="name" type="string" default=""/>
<variable id="2" name="level" type="int" default="1"/>
<variable id="3" name="coins" type="long"/>
<variable id="4" name="items" type="map[int,Item]"/>
<variable id="5" name="ids" type="list" value="int" javaType="IntList"/>
<variable id="6" name="tag" type="set[long]"/>
</bean>
<!-- 道具:嵌套 Bean -->
<bean name="Item">
<variable id="1" name="configId" type="int"/>
<variable id="2" name="count" type="int"/>
</bean>
<!-- 玩家表:long 主键 -> Player -->
<table name="tPlayer" key="long" value="Player"/>
<!-- 按服隔离的邮件表 -->
<table name="tMail" key="long" value="Mail" suffix="_@ServerId"/>
<!-- 纯内存计数表 -->
<table name="tCounter" key="long" value="Counter" memory="true"/>
<!-- 复合主键示例 -->
<beankey name="RoleServerKey">
<variable id="1" name="roleId" type="long"/>
<variable id="2" name="serverId" type="int"/>
</beankey>
<table name="tRoleServer" key="RoleServerKey" value="RoleServer"/>
<!-- 登录 Rpc -->
<bean name="LoginArg">
<variable id="1" name="account" type="string"/>
</bean>
<bean name="LoginRes">
<variable id="1" name="resultCode" type="long"/> <!-- 0 为正常 -->
<variable id="2" name="roleId" type="long"/>
</bean>
<rpc name="Login" argument="LoginArg" result="LoginRes" handle="server"/>
<!-- 单向协议 -->
<protocol name="CHeartbeat" argument="EmptyBean" handle="server"/>
<protocol name="SCoinChanged" argument="CoinChanged" handle="client"/>
<!-- 错误码 -->
<enum name="ERR_COIN_NOT_ENOUGH" value="1" comment="金币不足"/>
<enum name="ERR_NOT_FOUND" value="2" comment="玩家不存在"/>
<!-- 嵌套模块:背包 -->
<module name="bag" id="2">
<bean name="Bag">
<variable id="1" name="slots" type="map[int,Item]"/>
</bean>
<!-- dynamic 演示 -->
<bean name="BHorseExtra"/>
<bean name="BWingExtra"/>
<bean name="BagExtra">
<variable id="1" name="ext" type="dynamic">
<value bean="BHorseExtra"/>
<value bean="BWingExtra:2"/>
</variable>
</bean>
</module>
</module>
<!-- 引用手写 Bean -->
<external bean="Game.Common.BHandwritten"/>
<!-- 代码生成目标:游戏服 -->
<project name="GameServer" GenDir="gen/GameServer" SrcDir="src/GameServer" platform="java">
<ModuleStartOrder>
<module ref="role"/>
<module ref="role.bag"/>
</ModuleStartOrder>
<service name="GameServer" handle="server" base="main">
<module ref="role"/>
<module ref="role.bag"/>
</service>
</project>
<!-- HTTP 端点 -->
<servlet name="/api/health" TransactionLevel="None"/>
</solution>

运行代码生成器后,你会得到 PlayerItemBag 等 Bean 类、TableTPlayerTableTMail 等表类,以及 Login Rpc、CHeartbeat/SCoinChanged 协议的骨架代码。