-
第一步:先配置一个sbe的xml(trade.sbe.xml)
<?xml version="1.0" encoding="UTF-8"?><sbe:messageSchema xmlns:sbe="http://fixprotocol.io/2016/sbe"
package="com.baeldung.sbe.stub" id="1" version="0" semanticVersion="5.2"
description="A schema represents stock market data.">
<types>
<composite name="messageHeader" description="消息标识符和消息根的长度">
<type name="blockLength" primitiveType="uint16"/>
<type name="templateId" primitiveType="uint16"/>
<type name="schemaId" primitiveType="uint16"/>
<type name="version" primitiveType="uint16"/>
<type name="timestamp" primitiveType="uint64"/>
<type name="sequenceNumber" primitiveType="uint64"/>
<type name="messageType" primitiveType="uint8"/>
<type name="messageLength" primitiveType="uint32"/>
<type name="messageId" primitiveType="uint64"/>
<type name="messageStatus" primitiveType="uint8"/>
<type name="messageStatusReason" primitiveType="uint8"/>
</composite>
<enum name="Market" encodingType="uint8">
<validValue name="NYSE" description="纽约证券交易所">0</validValue>
<validValue name="NASDAQ" description="全国证券交易商协会自动报价系统">1</validValue>
</enum>
<type name="Symbol" primitiveType="char" length="4" characterEncoding="ASCII" description="股票代码"/>
<composite name="Decimal" >
<type name="mantissa" primitiveType="int64" description="尾数" minValue="0"/>
<type name="exponent" primitiveType="int8" description="指数" minValue="-128" maxValue="127"/>
</composite>
<enum name="Currency" encodingType="uint8" description="" >
<validValue name="USD" description="美元">0</validValue>
<validValue name="CNY" description="人民币">1</validValue>
</enum></types><composite name="Quote" description="报价代表股票在市场上的价格。"> <ref name="market" type="Market"/> <ref name="symbol" type="Symbol"/> <ref name="price" type="Decimal"/> <ref name="currency" type="Currency"/> </composite><sbe:message name="TradeData" id="1" description="代表报价和交易量">
<field name="quote" id="1" type="Quote" description="报价"/>
<field name="tradeVolume" id="2" type="uint16" description="交易量"/>
</sbe:message>
</sbe:messageSchema>
第二步:配置pom, 用maven命令去生成java文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>sbe-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>SBE Demo</name>
<description>Simple Binary Encoding Demo based on Baeldung tutorial</description>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 使用最新稳定版本 -->
<sbe.version>1.32.0</sbe.version>
<agrona.version>1.23.1</agrona.version>
<junit.version>5.10.1</junit.version>
</properties>
<dependencies>
<!-- Agrona - 高性能数据结构库,SBE 依赖 -->
<dependency>
<groupId>org.agrona</groupId>
<artifactId>agrona</artifactId>
<version>${agrona.version}</version>
</dependency>
<!-- SBE Tool - 用于代码生成 -->
<dependency>
<groupId>uk.co.real-logic</groupId>
<artifactId>sbe-tool</artifactId>
<version>${sbe.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<!-- 阿里云 Maven 镜像(国内推荐,速度快) -->
<repository>
<id>aliyunmaven</id>
<name>Aliyun Maven Repository</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!-- Maven 中央仓库(备用) -->
<repository>
<id>central</id>
<name>Maven Central Repository</name>
<url>https://repo1.maven.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<!-- Maven 插件仓库 -->
<pluginRepository>
<id>central</id>
<name>Maven Central Repository</name>
<url>https://repo1.maven.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<!-- Java 编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- SBE 代码生成插件 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.2.0</version>
<dependencies>
<dependency>
<groupId>uk.co.real-logic</groupId>
<artifactId>sbe-tool</artifactId>
<version>${sbe.version}</version>
</dependency>
<dependency>
<groupId>org.agrona</groupId>
<artifactId>agrona</artifactId>
<version>${agrona.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>generate-sbe-codecs-car</id>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>uk.co.real_logic.sbe.SbeTool</mainClass>
<includePluginDependencies>true</includePluginDependencies>
<classpathScope>compile</classpathScope>
<arguments>
<argument>${project.basedir}/src/main/resources/sbe/car.sbe.xml</argument>
</arguments>
<systemProperties>
<systemProperty>
<key>sbe.target.language</key>
<value>java</value>
</systemProperty>
<systemProperty>
<key>sbe.output.dir</key>
<value>${project.build.directory}/generated-sources/sbe</value>
</systemProperty>
<systemProperty>
<key>sbe.java.package</key>
<value>com.baeldung.sbe.generated</value>
</systemProperty>
<systemProperty>
<key>sbe.validation.stop.on.error</key>
<value>true</value>
</systemProperty>
</systemProperties>
</configuration>
</execution>
<execution>
<id>generate-sbe-codecs-trade</id>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>uk.co.real_logic.sbe.SbeTool</mainClass>
<includePluginDependencies>true</includePluginDependencies>
<classpathScope>compile</classpathScope>
<arguments>
<argument>${project.basedir}/src/main/resources/sbe/trade.sbe.xml</argument>
</arguments>
<systemProperties>
<systemProperty>
<key>sbe.target.language</key>
<value>java</value>
</systemProperty>
<systemProperty>
<key>sbe.output.dir</key>
<value>${project.build.directory}/generated-sources/sbe</value>
</systemProperty>
<systemProperty>
<key>sbe.validation.stop.on.error</key>
<value>true</value>
</systemProperty>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
<!-- 添加生成的源码目录 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<id>add-sbe-generated-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/sbe</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<!-- 测试插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
</project>
-
第三部, 执行maven install命令生成代码后, 尝试一下数据的编码和解码
package com.baeldung.sbe;
import java.math.BigDecimal;
import java.nio.ByteBuffer;import org.agrona.concurrent.UnsafeBuffer;
import com.baeldung.sbe.stub.Currency;
import com.baeldung.sbe.stub.Market;
import com.baeldung.sbe.stub.MessageHeaderDecoder;
import com.baeldung.sbe.stub.MessageHeaderEncoder;
import com.baeldung.sbe.stub.QuoteEncoder;
import com.baeldung.sbe.stub.TradeDataDecoder;
import com.baeldung.sbe.stub.TradeDataEncoder;public class TradeDemo {
public static void main(String[] args) {
System.out.println("=== TradeDemo ===");/** * =========第一步 创建数据======== */ // 绑定数据 MarketData marketData = new MarketData(2, 128.99, Market.NYSE, Currency.USD, "IBM"); // 转换价格 BigDecimal priceDecimal = BigDecimal.valueOf(marketData.getPrice()); int priceMantissa = priceDecimal.scaleByPowerOfTen(priceDecimal.scale()).intValue(); int priceExponent = priceDecimal.scale() * -1; /** * =========第二步 set数据======== */ // 创建缓冲区 UnsafeBuffer buffer = new UnsafeBuffer(ByteBuffer.allocateDirect(128)); // 创建消息头编码器 MessageHeaderEncoder headerEncoder = new MessageHeaderEncoder(); // 创建数据编码器 TradeDataEncoder tradeDataEncoder = new TradeDataEncoder(); // 绑定数据 TradeDataEncoder dataEncoder = tradeDataEncoder.wrapAndApplyHeader(buffer, 0, headerEncoder); dataEncoder.tradeVolume(marketData.getTradeVolume()); dataEncoder.quote() .market(marketData.getMarket()) .symbol(marketData.getSymbol()) .currency(marketData.getCurrency()) .price() .mantissa(priceMantissa) .exponent((byte) priceExponent); /** * =========第三步 get数据======== */ // 创建消息头解码器 MessageHeaderDecoder headerDecoder = new MessageHeaderDecoder(); TradeDataDecoder dataDecoder = new TradeDataDecoder(); // 解码数据 System.out.println("============打印结果==========="); dataDecoder.wrapAndApplyHeader(buffer, 0, headerDecoder); System.out.println("quoteId: " + dataDecoder.quoteId()); System.out.println("quote: " + dataDecoder.quote()); System.out.println("tradeVolume: " + dataDecoder.tradeVolume()); System.out.println("price: " + dataDecoder.quote().price()); System.out.println("priceMantissa: " + dataDecoder.quote().price().mantissa()); System.out.println("priceExponent: " + dataDecoder.quote().price().exponent()); System.out.println("market: " + dataDecoder.quote().market()); System.out.println("symbol: " + dataDecoder.quote().symbol()); System.out.println("currency: " + dataDecoder.quote().currency()); System.out.println("encodedLength: " + dataDecoder.encodedLength());}
}
参考:https:// baeldung. xiaocaicai. com/ java-sbe/
=============第二部分 ============
细心的朋友会发现, maven中还配置了个car.sbe.xml
那我们继续实现car.sbe.xml
<?xml version="1.0" encoding="UTF-8"?>
<sbe:messageSchema xmlns:sbe="http://www.fixprotocol.org/ns/sbe"
package="com.baeldung.sbe.generated"
id="1"
version="1"
semanticVersion="1.0"
description="Car example for SBE"
byteOrder="littleEndian">
<types>
<composite name="messageHeader" description="Message identifiers and length of message root">
<type name="blockLength" primitiveType="uint16"/>
<type name="templateId" primitiveType="uint16"/>
<type name="schemaId" primitiveType="uint16"/>
<type name="version" primitiveType="uint16"/>
</composite>
<enum name="BooleanType" encodingType="uint8">
<validValue name="FALSE">0</validValue>
<validValue name="TRUE">1</validValue>
</enum>
<enum name="Model" encodingType="uint8">
<validValue name="A">0</validValue>
<validValue name="B">1</validValue>
<validValue name="C">2</validValue>
</enum>
<enum name="Code" encodingType="uint8">
<validValue name="A">65</validValue>
<validValue name="B">66</validValue>
<validValue name="C">67</validValue>
</enum>
<composite name="groupSizeEncoding">
<type name="blockLength" primitiveType="uint16"/>
<type name="numInGroup" primitiveType="uint8"/>
</composite>
<composite name="varStringEncoding">
<type name="length" primitiveType="uint8"/>
<type name="varData" primitiveType="uint8" length="0" characterEncoding="UTF-8"/>
</composite>
<composite name="Engine">
<type name="capacity" primitiveType="uint16"/>
<type name="numCylinders" primitiveType="uint8"/>
<type name="maxRpm" primitiveType="uint16" presence="optional"/>
<type name="manufacturerCode" primitiveType="char" length="3"/>
<type name="efficiency" primitiveType="uint8"/>
<type name="boosterEnabled" primitiveType="uint8"/>
</composite>
</types>
<sbe:message name="Car" id="1" description="Represents a car">
<field name="serialNumber" id="1" type="uint64" description="Serial number"/>
<field name="modelYear" id="2" type="uint16" description="Model year"/>
<field name="available" id="3" type="BooleanType" description="Is available"/>
<field name="code" id="4" type="Code" description="Code"/>
<field name="someNumbers" id="5" type="uint8" description="Some numbers" presence="optional"/>
<field name="vehicleCode" id="6" type="char" length="6" description="Vehicle code"/>
<field name="extras" id="7" type="uint8" description="Extras"/>
<field name="discountedModel" id="8" type="Model" description="Discounted model"/>
<field name="engine" id="9" type="Engine" description="Engine information"/>
<group name="fuelFigures" id="10" dimensionType="groupSizeEncoding">
<field name="speed" id="11" type="uint16" description="Speed"/>
<field name="mpg" id="12" type="float" description="Miles per gallon"/>
<data name="usageDescription" id="13" type="varStringEncoding"/>
</group>
<group name="performanceFigures" id="14" dimensionType="groupSizeEncoding">
<field name="octaneRating" id="15" type="uint8" description="Octane rating"/>
<group name="acceleration" id="16" dimensionType="groupSizeEncoding">
<field name="mph" id="17" type="uint16" description="Miles per hour"/>
<field name="seconds" id="18" type="float" description="Seconds"/>
</group>
</group>
<data name="manufacturer" id="19" type="varStringEncoding"/>
<data name="model" id="20" type="varStringEncoding"/>
<data name="activationCode" id="21" type="varStringEncoding"/>
</sbe:message>
</sbe:messageSchema>
然后新增一个测试类:
SbeBasicTest
package com.baeldung.sbe;
import com.baeldung.sbe.generated.*;
import org.agrona.concurrent.UnsafeBuffer;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import java.nio.ByteBuffer;
/**
* SBE 基本用法测试
* 演示如何使用生成的 Encoder 和 Decoder
*/
public class SbeBasicTest {
@Test
public void testBasicEncodeDecode() {
// 1. 创建缓冲区
UnsafeBuffer buffer = new UnsafeBuffer(ByteBuffer.allocateDirect(4096));
// 2. 编码消息头
MessageHeaderEncoder headerEncoder = new MessageHeaderEncoder();
CarEncoder carEncoder = new CarEncoder();
int offset = 0;
headerEncoder.wrap(buffer, offset)
.blockLength(carEncoder.sbeBlockLength())
.templateId(carEncoder.sbeTemplateId())
.schemaId(carEncoder.sbeSchemaId())
.version(carEncoder.sbeSchemaVersion());
offset += headerEncoder.encodedLength();
// 3. 编码 Car 消息 - 基本字段
carEncoder.wrap(buffer, offset)
.serialNumber(12345L)
.modelYear(2024)
.available(BooleanType.TRUE)
.code(Code.C)
.extras((byte) 0)
.discountedModel(Model.A);
// 4. 编码 vehicleCode (固定长度字符数组,需要逐个设置)
String vehicleCode = "123456";
for (int i = 0; i < Math.min(6, vehicleCode.length()); i++) {
carEncoder.vehicleCode((byte) vehicleCode.charAt(i));
}
// 5. 编码 Engine
EngineEncoder engineEncoder = carEncoder.engine();
engineEncoder.capacity(4200)
.numCylinders((short) 8)
.maxRpm(5000)
.manufacturerCode("123")
.efficiency((short) 35)
.boosterEnabled((byte) 1);
// 6. 编码 fuelFigures 组
CarEncoder.FuelFiguresEncoder fuelFigures = carEncoder.fuelFiguresCount(2);
fuelFigures.next()
.speed(30)
.mpg(35.9f)
.usageDescription("Urban cycle");
fuelFigures.next()
.speed(55)
.mpg(49.0f)
.usageDescription("Highway cycle");
// 7. 编码 performanceFigures 组(包含嵌套组)
CarEncoder.PerformanceFiguresEncoder performanceFigures = carEncoder.performanceFiguresCount(1);
performanceFigures.next()
.octaneRating((short) 95);
performanceFigures.accelerationCount(2)
.next().mph(30).seconds(4.0f)
.next().mph(60).seconds(7.5f);
// 8. 编码变长字符串
carEncoder.manufacturer("Tesla");
carEncoder.model("Model S");
carEncoder.activationCode("ACT123");
// 9. 获取编码后的数据
int totalLength = carEncoder.encodedLength() + offset;
byte[] encodedData = new byte[totalLength];
buffer.getBytes(0, encodedData, 0, totalLength);
// 验证编码成功
assertNotNull(encodedData);
assertTrue(encodedData.length > 0);
System.out.println("编码成功,数据大小: " + encodedData.length + " bytes");
// ========== 解码部分 ==========
// 10. 创建解码缓冲区
UnsafeBuffer decodeBuffer = new UnsafeBuffer(encodedData);
// 11. 解码消息头
MessageHeaderDecoder headerDecoder = new MessageHeaderDecoder();
headerDecoder.wrap(decodeBuffer, 0);
int decodeOffset = headerDecoder.encodedLength();
// 12. 验证消息头
assertEquals(carEncoder.sbeTemplateId(), headerDecoder.templateId());
// 13. 解码 Car 消息
CarDecoder carDecoder = new CarDecoder();
carDecoder.wrap(decodeBuffer, decodeOffset,
headerDecoder.blockLength(),
headerDecoder.version());
// 14. 读取基本字段
assertEquals(12345L, carDecoder.serialNumber());
assertEquals(2024, carDecoder.modelYear());
assertEquals(BooleanType.TRUE, carDecoder.available());
assertEquals(Code.C, carDecoder.code());
assertEquals(Model.A, carDecoder.discountedModel());
// 15. 读取 Engine
EngineDecoder engine = carDecoder.engine();
assertEquals(4200, engine.capacity());
assertEquals(8, engine.numCylinders());
assertEquals(5000, engine.maxRpm());
assertEquals("123", engine.manufacturerCode());
assertEquals(35, engine.efficiency());
assertEquals(1, engine.boosterEnabled());
// 16. 读取 fuelFigures 组
CarDecoder.FuelFiguresDecoder fuelFiguresDecoder = carDecoder.fuelFigures();
assertTrue(fuelFiguresDecoder.hasNext());
fuelFiguresDecoder.next();
assertEquals(30, fuelFiguresDecoder.speed());
assertEquals(35.9f, fuelFiguresDecoder.mpg(), 0.01f);
assertEquals("Urban cycle", fuelFiguresDecoder.usageDescription());
assertTrue(fuelFiguresDecoder.hasNext());
fuelFiguresDecoder.next();
assertEquals(55, fuelFiguresDecoder.speed());
assertEquals(49.0f, fuelFiguresDecoder.mpg(), 0.01f);
assertEquals("Highway cycle", fuelFiguresDecoder.usageDescription());
// 17. 读取 performanceFigures 组
CarDecoder.PerformanceFiguresDecoder perfFiguresDecoder = carDecoder.performanceFigures();
assertTrue(perfFiguresDecoder.hasNext());
perfFiguresDecoder.next();
assertEquals(95, perfFiguresDecoder.octaneRating());
// 读取嵌套的 acceleration 组
CarDecoder.PerformanceFiguresDecoder.AccelerationDecoder acceleration =
perfFiguresDecoder.acceleration();
assertTrue(acceleration.hasNext());
acceleration.next();
assertEquals(30, acceleration.mph());
assertEquals(4.0f, acceleration.seconds(), 0.01f);
assertTrue(acceleration.hasNext());
acceleration.next();
assertEquals(60, acceleration.mph());
assertEquals(7.5f, acceleration.seconds(), 0.01f);
// 18. 读取变长字符串
assertEquals("Tesla", carDecoder.manufacturer());
assertEquals("Model S", carDecoder.model());
assertEquals("ACT123", carDecoder.activationCode());
System.out.println("解码成功!");
System.out.println("序列号: " + carDecoder.serialNumber());
System.out.println("年份: " + carDecoder.modelYear());
System.out.println("制造商: " + carDecoder.manufacturer());
System.out.println("型号: " + carDecoder.model());
}
@Test
public void testSimpleEncodeDecode() {
// 简化版本:只编码基本字段和字符串
UnsafeBuffer buffer = new UnsafeBuffer(ByteBuffer.allocateDirect(1024));
MessageHeaderEncoder headerEncoder = new MessageHeaderEncoder();
CarEncoder carEncoder = new CarEncoder();
int offset = 0;
headerEncoder.wrap(buffer, offset)
.blockLength(carEncoder.sbeBlockLength())
.templateId(carEncoder.sbeTemplateId())
.schemaId(carEncoder.sbeSchemaId())
.version(carEncoder.sbeSchemaVersion());
offset += headerEncoder.encodedLength();
// 只编码基本字段
carEncoder.wrap(buffer, offset)
.serialNumber(99999L)
.modelYear(2023)
.available(BooleanType.FALSE)
.code(Code.A)
.extras((short) 0)
.discountedModel(Model.B);
// 设置 vehicleCode
String vCode = "ABC123";
for (int i = 0; i < Math.min(6, vCode.length()); i++) {
carEncoder.vehicleCode((byte) vCode.charAt(i));
}
// 编码 Engine(简化)
carEncoder.engine()
.capacity(3000)
.numCylinders((short) 6)
.manufacturerCode("XYZ")
.efficiency((short) 30)
.boosterEnabled((byte) 0);
// 编码字符串
carEncoder.manufacturer("BMW");
carEncoder.model("X5");
carEncoder.activationCode("CODE999");
// 提取数据
int totalLength = carEncoder.encodedLength() + offset;
byte[] data = new byte[totalLength];
buffer.getBytes(0, data, 0, totalLength);
// 解码
UnsafeBuffer decodeBuffer = new UnsafeBuffer(data);
MessageHeaderDecoder headerDecoder = new MessageHeaderDecoder();
headerDecoder.wrap(decodeBuffer, 0);
CarDecoder decoder = new CarDecoder();
decoder.wrap(decodeBuffer, headerDecoder.encodedLength(),
headerDecoder.blockLength(), headerDecoder.version());
// 验证
assertEquals(99999L, decoder.serialNumber());
assertEquals(2023, decoder.modelYear());
assertEquals(BooleanType.FALSE, decoder.available());
assertEquals(Code.A, decoder.code());
assertEquals("BMW", decoder.manufacturer());
assertEquals("X5", decoder.model());
assertEquals("CODE999", decoder.activationCode());
EngineDecoder engine = decoder.engine();
assertEquals(3000, engine.capacity());
assertEquals(6, engine.numCylinders());
assertEquals("XYZ", engine.manufacturerCode());
}
@Test
public void testRoundTrip() {
// 往返测试:编码后解码,验证数据一致性
UnsafeBuffer buffer = new UnsafeBuffer(ByteBuffer.allocateDirect(2048));
// 编码
MessageHeaderEncoder headerEncoder = new MessageHeaderEncoder();
CarEncoder carEncoder = new CarEncoder();
int offset = 0;
headerEncoder.wrap(buffer, offset)
.blockLength(carEncoder.sbeBlockLength())
.templateId(carEncoder.sbeTemplateId())
.schemaId(carEncoder.sbeSchemaId())
.version(carEncoder.sbeSchemaVersion());
offset += headerEncoder.encodedLength();
long serialNumber = 88888L;
int modelYear = 2024;
String manufacturer = "Mercedes";
String model = "S-Class";
carEncoder.wrap(buffer, offset)
.serialNumber(serialNumber)
.modelYear(modelYear)
.available(BooleanType.TRUE)
.code(Code.B)
.extras((short) 0)
.discountedModel(Model.C);
String vCode = "MERC01";
for (int i = 0; i < 6; i++) {
carEncoder.vehicleCode((byte) vCode.charAt(i));
}
carEncoder.engine()
.capacity(4500)
.numCylinders((short) 12)
.maxRpm(6000)
.manufacturerCode("MBZ")
.efficiency((short) 40)
.boosterEnabled((byte) 1);
carEncoder.manufacturer(manufacturer);
carEncoder.model(model);
carEncoder.activationCode("MERC123");
int totalLength = carEncoder.encodedLength() + offset;
byte[] encoded = new byte[totalLength];
buffer.getBytes(0, encoded, 0, totalLength);
// 解码
UnsafeBuffer decodeBuffer = new UnsafeBuffer(encoded);
MessageHeaderDecoder headerDecoder = new MessageHeaderDecoder();
headerDecoder.wrap(decodeBuffer, 0);
CarDecoder decoder = new CarDecoder();
decoder.wrap(decodeBuffer, headerDecoder.encodedLength(),
headerDecoder.blockLength(), headerDecoder.version());
// 验证往返一致性
assertEquals(serialNumber, decoder.serialNumber());
assertEquals(modelYear, decoder.modelYear());
assertEquals(manufacturer, decoder.manufacturer());
assertEquals(model, decoder.model());
EngineDecoder engine = decoder.engine();
assertEquals(4500, engine.capacity());
assertEquals(12, engine.numCylinders());
assertEquals(6000, engine.maxRpm());
assertEquals("MBZ", engine.manufacturerCode());
System.out.println("往返测试通过!");
}
}
最后贴一下目录结构:
