扁平化写法示例
2024年3月9日小于 1 分钟
扁平化写法示例
提示
- 在阅读本文之前,建议先阅读 协议格式说明
- 所谓的 扁平化写法 就是不用单独封装
Header
和Body
,而是直接将Header
和Body
的数据写在同一个实体类中
实体类定义
Rust 命名风格
@Setter
@Getter
@ToString
public class RustStyleDebugEntity01Flatten {
/// ///////////////////// header
// 固定为 0x80901234
@Preset.RustStyle.i32
private int magicNumber;
// 主版本号 无符号数 1字节
@Preset.RustStyle.u8
private short majorVersion;
// 次版本号 无符号数 1字节
@Preset.RustStyle.u8
private short minorVersion;
// 消息类型 无符号数 2字节
@Preset.RustStyle.u16
private int msgType;
// 消息体长度 无符号数 2字节
@Preset.RustStyle.u16
private int msgBodyLength;
/// ///////////////////// body
// 下一个字段(username)长度 无符号数 2字节
@Preset.RustStyle.u16
private int usernameLength;
// 用户名 String, "UTF-8"
@Preset.RustStyle.str(lengthExpression = "getUsernameLength()")
private String username;
// 下一个字段(password)长度 无符号数 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" 8字节
@Preset.RustStyle.str(length = 8)
private String birthday;
// 手机号 BCD_8421[6] 6字节(12个数字)
@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 RawStyleDebugEntity01Flatten {
/// ///////////////////// 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;
// 消息体长度 无符号数 2字节
@XtreamField(length = 2)
private int msgBodyLength;
/// ///////////////////// 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"
@XtreamField(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 JtStyleDebugEntity01Flatten {
/// ///////////////////// 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;
// 消息体长度 无符号数 2字节
@Preset.JtStyle.Word
private int msgBodyLength;
/// ///////////////////// 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]
@Preset.JtStyle.Bcd(length = 6)
private String phoneNumber;
// 年龄 无符号数 2字节
@Preset.JtStyle.Word
private int age;
// 状态 有符号数 2字节
@Preset.JtStyle.Word
private short status;
}
JT/T 808 命名风格(简化)
@Setter
@Getter
@ToString
// 这里使用了 prependLengthFieldType 和 prependLengthFieldLength 属性
// 从而省略了 usernameLength 和 passwordLength
public class JtStyleDebugEntity01FlattenSimple {
//////////////////////// 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;
// 消息体长度 无符号数 2字节
@Preset.JtStyle.Word
private int msgBodyLength;
//////////////////////// body
// 用户名 String, "UTF-8"
// prependLengthFieldType: 前面自动添加一个u16类型字段作为该字段的长度字段
@Preset.JtStyle.Str(charset = "UTF-8", prependLengthFieldType = PrependLengthFieldType.u16)
private String username;
// 密码 String, "GBK"
// prependLengthFieldType: 前面自动添加一个u16类型(2字节)字段作为该字段的长度字段
@Preset.JtStyle.Str(charset = XtreamConstants.CHARSET_NAME_GBK, prependLengthFieldLength = 2)
private String password;
// 生日 String[8], "yyyyMMdd", "UTF-8"
@Preset.JtStyle.Str(charset = "UTF-8", length = 8)
private String birthday;
// 手机号 BCD_8421[6]
@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 JtStyleDebugEntity01Flatten entity = entityCodec.decode(JtStyleDebugEntity01Flatten.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 JtStyleDebugEntity01Flatten instance = new JtStyleDebugEntity01Flatten();
// 省略属性赋值
// instance.setXxx(someValue);
// ...
instance.setMajorVersion((short) 1);
// 将 instance 的数据序列化到 buffer 中
entityCodec.encode(instance, buffer);
// 使用 buffer
System.out.println(ByteBufUtil.hexDump(buffer));
} finally {
buffer.release();
}
}
}