Dubbo编解码(三)-TransportCodec

Dubbo编解码系列文章目录

Dubbo编解码(一)-原理
Dubbo编解码(二)-Codec2和AbstractCodec
Dubbo编解码(三)-TransportCodec
Dubbo编解码(五)-Dubbo协议编码器
Dubbo编解码(六)-Dubbo协议解码器


TransportCodec-传输层编解码

继承了 抽象类AbstractCodec
实现了 扩展点接口Codec2的encode和decode方法

encode

@Override
public void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException {
	OutputStream output = new ChannelBufferOutputStream(buffer);
	// 把 字节输出流-output 写入到 对象输出-objectOutput 里面
	// 序列化,所有serialize方法的具体实现 的 返回对象,都实现了ObjectOutput接口,ex: Hessian2ObjectOutput
	// 针对序列化扩展点的serialize方法后面整理
	ObjectOutput objectOutput = getSerialization(channel).serialize(channel.getUrl(), output);
	encodeData(channel, objectOutput, message);
	objectOutput.flushBuffer();
	if (objectOutput instanceof Cleanable) {
		((Cleanable) objectOutput).cleanup();
	}
}

decode

@Override
public Object decode(Channel channel, ChannelBuffer buffer) throws IOException {
	InputStream input = new ChannelBufferInputStream(buffer);
	// 反序列化
	ObjectInput objectInput = getSerialization(channel).deserialize(channel.getUrl(), input);
	Object object = decodeData(channel, objectInput);
	if (objectInput instanceof Cleanable) {
		((Cleanable) objectInput).cleanup();
	}
	return object;
}

encodeData和decodeData

TransportCodec 还定义了encodeData、decodeData
ObjectOutput、ObjectInput的具体实现分别是ChannelBufferOutputStream、ChannelBufferInputStream

protected void encodeData(Channel channel, ObjectOutput output, Object message) throws IOException {
	encodeData(output, message);
}

protected void encodeData(ObjectOutput output, Object message) throws IOException {
	// 对应ObjectOutput具体实现类的writeObject方法
	output.writeObject(message);
}

protected Object decodeData(Channel channel, ObjectInput input) throws IOException {
	return decodeData(input);
}

protected Object decodeData(ObjectInput input) throws IOException {
	try {
		// 对应ObjectInput具体实现类的readObject方法
		return input.readObject();
	} catch (ClassNotFoundException e) {
		throw new IOException("ClassNotFoundException: " + StringUtils.toString(e));
	}
}

ChannelBufferOutputStream-通道缓存输出流

主要作用就是针对ChannelBuffer的写操作做封装
ChannelBufferOutputStream继承了抽象类OutputStream
针对抽象类OutputStream的具体实现和覆写 都是使用 ChannelBuffer#writeBytes
所以 外部调用ChannelBufferOutputStream#write 其实就是 操作 ChannelBuffer#writeBytes

成员变量

private final ChannelBuffer buffer;
private final int startIndex;

构造方法

public ChannelBufferOutputStream(ChannelBuffer buffer) {
	if (buffer == null) {
		throw new NullPointerException("buffer");
	}
	this.buffer = buffer;
	// 用buffer的写索引writerIndex初始化startIndex
	startIndex = buffer.writerIndex();
}

覆写、实现OutputStream

// 覆写
@Override
public void write(byte[] b, int off, int len) throws IOException {
	if (len == 0) {
		return;
	}
	// TODO 涉及Netty源码
	buffer.writeBytes(b, off, len);
}

@Override
public void write(byte[] b) throws IOException {
	buffer.writeBytes(b);
}

// 实现
@Override
public void write(int b) throws IOException {
	buffer.writeByte((byte) b);
}

ChannelBufferInputStream-通道缓存输入流

和ChannelBufferOutputStream类似

成员变量

private final ChannelBuffer buffer;
private final int startIndex;
private final int endIndex;

构造方法

public ChannelBufferInputStream(ChannelBuffer buffer) {
	// buffer.readableBytes() = 写索引位置 - 读索引位置
	this(buffer, buffer.readableBytes());
}

public ChannelBufferInputStream(ChannelBuffer buffer, int length) {
	// ...

	this.buffer = buffer;
	// 起始位置 = 读索引位置
	startIndex = buffer.readerIndex();
	// 结束位置 = 读索引位置 + (写索引位置 - 读索引位置)
	endIndex = startIndex + length;
	// 标记读索引
	buffer.markReaderIndex();
}

覆写、实现InputStream

// 覆写
@Override
public int available() throws IOException {
	// 是否可读 = 结束位置 - 当前读索引位置
	return endIndex - buffer.readerIndex();
}

@Override
public void mark(int readlimit) {
	// 对当前readerIndex做标记
	buffer.markReaderIndex();
}

@Override
public boolean markSupported() {
	return true;
}

@Override
public int read(byte[] b, int off, int len) throws IOException {
	int available = available();
	if (available == 0) {
		return -1;
	}

	// 取 可读长度 和 准备读取长度 的 较小值
	len = Math.min(available, len);
	buffer.readBytes(b, off, len);
	return len;
}

@Override
public void reset() throws IOException {
	// 重置 buffer的读索引位置 = markedReaderIndex
	buffer.resetReaderIndex();
}

@Override
public long skip(long n) throws IOException {
	if (n > Integer.MAX_VALUE) {
		return skipBytes(Integer.MAX_VALUE);
	} else {
		return skipBytes((int) n);
	}
}

private int skipBytes(int n) throws IOException {
	int nBytes = Math.min(available(), n);
	// 跳过指定长度的字节,就是将readerIndex设置为 当前readerIndex+n,并且不能超过当前writerIndex
	buffer.skipBytes(nBytes);
	// 返回跳过的字节数
	return nBytes;
}

// 实现
@Override
public int read() throws IOException {
	// 如果buffer不可读,也就是可读字节数<0
	if (!buffer.readable()) {
		return -1;
	}
	// 读取一个字节
	return buffer.readByte() & 0xff;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值