跳到主要内容

pb、json 数据协议扩展

介绍

框架支持同样的一套业务代码,无需变更就能支持不同的业务数据协议,如 protobuf、json,并支持扩展。 在框架中切换协议是简单的,只需要一行代码。

框架目前只内置了 jprotobuf 业务数据协议编解码。现在,我们学习如何扩展 json 编解码器。 学习完本篇内容后,你将可以扩展任意的业务数据协议编解码。

扩展 json 编解码

现在,我们使用 jackson 扩展一个 json 编解码器。


添加 jackson

pom.xml
<!-- https://mvnrepository.com/artifact/tools.jackson.core/jackson-databind -->
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>3.0.0</version>
</dependency>

自定义 json 编解码类,实现 DataCodec 接口。

@Slf4j
public class JsonDataCodec implements DataCodec {
@Override
public byte[] encode(Object data) {

if (Objects.isNull(data)) {
return CommonConst.emptyBytes;
}

try {
return JsonKit.objectMapper.writeValueAsBytes(data);
} catch (Throwable e) {
log.error(e.getMessage(), e);
}

return CommonConst.emptyBytes;
}

@Override
public <T> T decode(byte[] data, Class<T> dataClass) {

if (ArrayKit.isEmpty(data)) {
return null;
}

try {
return JsonKit.objectMapper.readValue(data, dataClass);
} catch (Throwable e) {
log.error(e.getMessage(), e);
}

return null;
}
}

@Slf4j
@UtilityClass
public class JsonKit {
final ObjectMapper objectMapper = JsonMapper.builder()
.enable(SerializationFeature.INDENT_OUTPUT)
.build();

public String toJson(Object object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JacksonException e) {
log.error(e.getMessage(), e);
}

return "{}";
}
}

  • code 3,设置 json 编解码
class OneApplication {
static void main() {
DataCodecManager.setDataCodec(new JsonDataCodec());
...
new RunOne()
...
.startup();
}
}

仅需要两步,我们就完成 json 的扩展了

  1. 自定义 json 编解码类,实现 DataCodec 接口。
  2. 设置到 DataCodecManager 中。

action 业务代码

让我们先看一个 action 的业务代码片段。

@ActionController(19)
public class JsonAction {
@ActionMethod(1)
public HelloMessage hello(HelloMessage message) {
message.name = message.name + ",hello json";
return message;
}
}

@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class HelloMessage {
public String name;
}

细心的朋友会发现 HelloMessage 中有 ProtobufClass 注解,不必担心,这并不会影响我们的代码运行。 这里的 ProtobufClass 注解是没有任何作用的,因为我们现在使用的是 json 编解码器, 简单点说 ProtobufClass 注解是可有可无的。

既然 HelloMessage 类中的 ProtobufClass 注解可有可无,那么为什么还要写在这里呢? 这里想要表达的是,如果我们之前的项目使用的是默认的编解码器 jprotobuf , 那么可以实现无需修改任何代码就能支持 json 格式。

这意味着我们可以使用一套业务代码,在不改动的情况下就能支持不同的数据协议。

注意事项

框架默认的数据协议编解码是 jprotobuf,如果使用了自定义编解码,那么请求端也需要与服务器保持同样的数据协议编解码。比如

class OneClient {
static void main() {
DataCodecManager.setDataCodec(new JsonDataCodec());

new ClientRunOne()
...
.startup();
}
}