前言
本文,我们会将协议和代码中的Request,Response对应起来。
正文
按照上文的设计,我们有Message,Request,Response三个概念,仅考虑Protobuf,最终的代码实现如下图
image.png顶层——MessageHeader和AbstractMessage
消息可能会包含一些额外信息(moduleId,commandId,发送时间等等),将这些信息放在MessageHeader里,以便拓展
public class MessageHeader {
private final int moduleId;
private final int commandId;
public MessageHeader(int moduleId, int commandId) {
this.moduleId = moduleId;
this.commandId = commandId;
}
public int getModuleId() {
return moduleId;
}
public int getCommandId() {
return commandId;
}
}
消息还必须有实际数据body,它在传输过程中会进行编码和解码.因此我们也必须有编解码方法,定义AbstractMessage如下
public abstract class AbstractMessage {
private MessageHeader header;
private Object body;
public MessageHeader header() {
return header;
}
public Object body() {
return body;
}
public abstract void decode() throws Exception;
public abstract void encode();
public void setHeader(MessageHeader header) {
this.header = header;
}
public void setBody(Object body) {
this.body = body;
}
@Override
public String toString() {
return "AbstractMessage{" +
"header=" + header +
", body=" + body +
'}';
}
}
Request
Request的header目前和MessageHeader一致,直接继承一下
public class RequestHeader extends MessageHeader {
public RequestHeader(int moduleId, int commandId) {
super(moduleId, commandId);
}
}
定义AbstractRequest如下
public abstract class AbstractRequest extends AbstractMessage {
@Override
public RequestHeader header() {
return (RequestHeader) super.header();
}
@Override
public ByteString body() {
return (ByteString) super.body();
}
}
Response
Response的header多出了errorCode,定义ResponseHeader如下
public class ResponseHeader extends MessageHeader {
private final int errorCode;
public ResponseHeader(int moduleId, int commandId, int errorCode) {
super(moduleId, commandId);
this.errorCode = errorCode;
}
public int errorCode() {
return errorCode;
}
public int getErrorCode() {
return errorCode;
}
}
定义AbstractResponse如下
public abstract class AbstractResponse extends AbstractMessage {
@Override
public ResponseHeader header() {
return (ResponseHeader) super.header();
}
@Override
public ByteString body() {
return (ByteString) super.body();
}
}
示例
下面展示一个Request,一个Response.这里我们借助protobuf简化, 直接在内部封装下Protobuf的原始数据.
encode和decode方法后续可能通过其他方式优化,如反射.
public class HelloRequest extends AbstractRequest {
private Hello.HelloMessage body;
@Override
public void decode() throws InvalidProtocolBufferException {
body = Hello.HelloMessage.parseFrom(body());
}
@Override
public void encode() {
setBody(body.toByteString());
}
public Hello.HelloMessage getBody() {
return body;
}
public void setBody(Hello.HelloMessage body) {
this.body = body;
}
}
public class HelloResponse extends AbstractResponse {
private Hello.MeToMessage body;
@Override
public void decode() throws InvalidProtocolBufferException {
body = Hello.MeToMessage.parseFrom(body());
}
@Override
public void encode() {
setBody(body.toByteString());
}
public Hello.MeToMessage getBody() {
return body;
}
public void setBody(Hello.MeToMessage body) {
this.body = body;
}
}
至此,Request,Response的封装结束
后记
这一阶段经历了很长时间,主要有三点比较困惑
-
是否需要MessageHeader
-
编码解码到底如何做
-
怎么才能支持多种数据格式(Protobuf,JSON等等)
这几点的核心问题是相同的, 做的太少,设想的太多,导致后面没办法进行下去, 认识的这一点后,开始边做边试.最终这三个问题通过 "堵疏斩替"全都解决了
-
是否需要MessageHeader
需要,Request和Response包含的元数据部分是不同的.并且他们需要是可拓展的, -
编解码到底如何做
AbstractMessage暴露body给子类,再加上利用Protobuf自有的功能,最终实现的时候出乎意料的简单
-
先用protobuf,真的有其他格式的需求了再做
网友评论