嵌套写法示例
2024年3月9日小于 1 分钟
嵌套写法示例
提示
- 在阅读本文之前,建议先阅读 协议格式说明
- 所谓的 嵌套写法 就是将
Header
和Body
分别封装到单独的实体类中。
实体类定义
Rust 命名风格
@Setter
@Getter
@ToString
public class RustStyleDebugEntity01Nested {
// 整个 Header 封装到一个实体类中
@Preset.RustStyle.struct
private Header header;
// 消息体长度 无符号数 2字节
@Preset.RustStyle.u16
private int msgBodyLength;
// 整个 Body 封装到一个实体类中
@Preset.RustStyle.struct
private Body body;
// 下面是 Header 和 Body 实体类的声明
@Data
public static class Header {
// 固定为 0x80901234
@Preset.RustStyle.i32
private int magicNumber = 0x80901234;
// 主版本号 无符号数 1字节
@Preset.RustStyle.u8
private short majorVersion;
// 次版本号 无符号数 1字节
@Preset.RustStyle.u8
private short minorVersion;
// 消息类型 无符号数 2字节
@Preset.RustStyle.u16
private int msgType;
}
@Data
public static class Body {
// 下一个字段长度 无符号数 2字节
@Preset.RustStyle.u16
private int usernameLength;
// 用户名 String, "UTF-8"
@Preset.RustStyle.str(lengthExpression = "getUsernameLength()")
private String username;
// 下一个字段长度 无符号数 2字节
@Preset.RustStyle.u16
private int passwordLength;
// 密码 String, "GBK"
@Preset.RustStyle.str(charset = XtreamConstants.CHARSET_NAME_GBK, lengthExpression = "getPasswordLength()")
private String password;
// 生日 String[8], "yyyyMMdd", "UTF-8"
@Preset.RustStyle.str(length = 8)
private String birthday;
// 手机号 BCD_8421[6] "GBK"
@Preset.RustStyle.str(charset = XtreamConstants.CHARSET_NAME_BCD_8421, length = 6)
private String phoneNumber;
// 年龄 无符号数 2字节
@Preset.RustStyle.u16
private int age;
// 状态 有符号数 2字节
@Preset.RustStyle.i16
private short status;
}
}
原始命名风格
@Setter
@Getter
@ToString
public class RawStyleDebugEntity01Nested {
// 整个 Header 封装到一个实体类中
@XtreamField(dataType = BeanPropertyMetadata.FiledDataType.struct)
private Header header;
// 消息体长度 无符号数 2字节
@XtreamField(length = 2)
private int msgBodyLength;
// 整个 Body 封装到一个实体类中
@XtreamField(dataType = BeanPropertyMetadata.FiledDataType.struct)
private Body body;
// 下面是 Header 和 Body 实体类的声明
@Data
public static class Header {
// 固定为 0x80901234
@XtreamField(length = 4)
private int magicNumber = 0x80901234;
// 主版本号 无符号数 1字节
@XtreamField(length = 1)
private short majorVersion;
// 次版本号 无符号数 1字节
@XtreamField(length = 1)
private short minorVersion;
// 消息类型 无符号数 2字节
@XtreamField(length = 2)
private int msgType;
}
@Data
public static class Body {
// 下一个字段长度 无符号数 2字节
@XtreamField(length = 2)
private int usernameLength;
// 用户名 String, "UTF-8"
@XtreamField(charset = "utf-8", lengthExpression = "getUsernameLength()")
private String username;
// 下一个字段长度 无符号数 2字节
@XtreamField(length = 2)
private int passwordLength;
// 密码 String, "GBK"
@Preset.RustStyle.str(charset = XtreamConstants.CHARSET_NAME_GBK, lengthExpression = "getPasswordLength()")
private String password;
// 生日 String[8], "yyyyMMdd", "UTF-8"
@XtreamField(charset = "UTF-8", length = 8)
private String birthday;
// 手机号 BCD_8421[6] "GBK"
@XtreamField(charset = XtreamConstants.CHARSET_NAME_BCD_8421, length = 6)
private String phoneNumber;
// 年龄 无符号数 2字节
@XtreamField(length = 2)
private int age;
// 状态 有符号数 2字节
@XtreamField(length = 2)
private short status;
}
}
JT/T 808 命名风格
@Setter
@Getter
@ToString
public class JtStyleDebugEntity01Nested {
// 整个 Header 封装到一个实体类中
@Preset.JtStyle.Object
private Header header;
// 消息体长度 无符号数 2字节
@Preset.JtStyle.Word
private int msgBodyLength;
// 整个 Body 封装到一个实体类中
@Preset.JtStyle.Object
private Body body;
// 下面是 Header 和 Body 实体类的声明
@Data
public static class Header {
// 固定为 0x80901234
@Preset.JtStyle.Dword
private int magicNumber = 0x80901234;
// 主版本号 无符号数 1字节
@Preset.JtStyle.Byte
private short majorVersion;
// 次版本号 无符号数 1字节
@Preset.JtStyle.Byte
private short minorVersion;
// 消息类型 无符号数 2字节
@Preset.JtStyle.Word
private int msgType;
}
@Data
public static class Body {
// 下一个字段长度 无符号数 2字节
@Preset.JtStyle.Word
private int usernameLength;
// 用户名 String, "UTF-8"
@Preset.JtStyle.Str(charset = "UTF-8", lengthExpression = "getUsernameLength()")
private String username;
// 下一个字段长度 无符号数 2字节
@Preset.JtStyle.Word
private int passwordLength;
// 密码 String, "GBK"
@Preset.JtStyle.Str(charset = XtreamConstants.CHARSET_NAME_GBK, lengthExpression = "getPasswordLength()")
private String password;
// 生日 String[8], "yyyyMMdd", "UTF-8"
@Preset.JtStyle.Str(charset = "UTF-8", length = 8)
private String birthday;
// 手机号 BCD_8421[6] "GBK"
@Preset.JtStyle.Bcd(length = 6)
private String phoneNumber;
// 年龄 无符号数 2字节
@Preset.JtStyle.Word
private int age;
// 状态 有符号数 2字节
@Preset.JtStyle.Word
private short status;
}
}
反序列化
public class EntityDecodeTest {
@Test
void testDecode() {
final EntityCodec entityCodec = EntityCodec.DEFAULT;
// buffer 中存储的是要反序列化的数据(这里写死用来演示)
final String hexString = "8090123401020001003d001678747265616d2d636f6465632ee794a8e688b7e5908d001178747265616d2d636f6465632ec3dcc2eb3230323130323033013911112222270fff9c";
final ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer().writeBytes(XtreamBytes.decodeHex(hexString));
try {
final RustStyleDebugEntity01Nested entity = entityCodec.decode(RustStyleDebugEntity01Nested.class, buffer);
System.out.println(entity);
} finally {
buffer.release();
}
}
}
序列化
public class EntityEncodeTest {
@Test
void testEncode() {
final EntityCodec entityCodec = EntityCodec.DEFAULT;
final ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
try {
final RustStyleDebugEntity01Nested instance = new RustStyleDebugEntity01Nested();
// 省略属性赋值
// instance.setXxx(someValue);
// ...
instance.setHeader(...);
// 将 instance 的数据序列化到 buffer 中
entityCodec.encode(instance, buffer);
// 使用 buffer
System.out.println(ByteBufUtil.hexDump(buffer));
} finally {
buffer.release();
}
}
}