序
本文次要钻研一下 RedisTokenVisitor
RedisTokenVisitor
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/protocol/RedisTokenVisitor.java
public interface RedisTokenVisitor<T> {T array(ArrayRedisToken token);
T status(StatusRedisToken token);
T string(StringRedisToken token);
T integer(IntegerRedisToken token);
T error(ErrorRedisToken token);
T unknown(UnknownRedisToken token);
static <T> LambdaRedisTokenVisitor.Builder<T> builder() {return new LambdaRedisTokenVisitor.Builder<>();
}
}
- RedisTokenVisitor 接口定义了 array、status、string、integer、error、unknown 办法,并提供了动态 builder 办法用于创立 LambdaRedisTokenVisitor.Builder
AbstractRedisTokenVisitor
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/protocol/AbstractRedisTokenVisitor.java
public abstract class AbstractRedisTokenVisitor<T> implements RedisTokenVisitor<T> {
@Override
public T array(ArrayRedisToken token) {return null;}
@Override
public T status(StatusRedisToken token) {return null;}
@Override
public T string(StringRedisToken token) {return null;}
@Override
public T error(ErrorRedisToken token) {return null;}
@Override
public T unknown(UnknownRedisToken token) {return null;}
@Override
public T integer(IntegerRedisToken token) {return null;}
}
- AbstractRedisTokenVisitor 实现了 RedisTokenVisitor 接口,默认返回 null
LambdaRedisTokenVisitor
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/protocol/LambdaRedisTokenVisitor.java
class LambdaRedisTokenVisitor<T> implements RedisTokenVisitor<T> {
private Function<ArrayRedisToken, T> onArray;
private Function<StatusRedisToken, T> onStatus;
private Function<StringRedisToken, T> onString;
private Function<ErrorRedisToken, T> onError;
private Function<IntegerRedisToken, T> onInteger;
private Function<UnknownRedisToken, T> onUnknown;
LambdaRedisTokenVisitor(
Function<ArrayRedisToken, T> onArray,
Function<StatusRedisToken, T> onStatus,
Function<StringRedisToken, T> onString,
Function<ErrorRedisToken, T> onError,
Function<IntegerRedisToken, T> onInteger,
Function<UnknownRedisToken, T> onUnknown) {
this.onArray = onArray;
this.onStatus = onStatus;
this.onString = onString;
this.onError = onError;
this.onInteger = onInteger;
this.onUnknown = onUnknown;
}
@Override
public T array(ArrayRedisToken token) {return onArray.apply(token);
}
@Override
public T status(StatusRedisToken token) {return onStatus.apply(token);
}
@Override
public T string(StringRedisToken token) {return onString.apply(token);
}
@Override
public T error(ErrorRedisToken token) {return onError.apply(token);
}
@Override
public T unknown(UnknownRedisToken token) {return onUnknown.apply(token);
}
@Override
public T integer(IntegerRedisToken token) {return onInteger.apply(token);
}
public static class Builder<T> {
private Function<ArrayRedisToken, T> onArray;
private Function<StatusRedisToken, T> onStatus;
private Function<StringRedisToken, T> onString;
private Function<ErrorRedisToken, T> onError;
private Function<IntegerRedisToken, T> onInteger;
private Function<UnknownRedisToken, T> onUnknown;
public Builder<T> onArray(Function<ArrayRedisToken, T> onArray) {this.onArray = requireNonNull(onArray);
return this;
}
public Builder<T> onStatus(Function<StatusRedisToken, T> onStatus) {this.onStatus = requireNonNull(onStatus);
return this;
}
public Builder<T> onString(Function<StringRedisToken, T> onString) {this.onString = requireNonNull(onString);
return this;
}
public Builder<T> onError(Function<ErrorRedisToken, T> onError) {this.onError = requireNonNull(onError);
return this;
}
public Builder<T> onInteger(Function<IntegerRedisToken, T> onInteger) {this.onInteger = requireNonNull(onInteger);
return this;
}
public Builder<T> onUnknown(Function<UnknownRedisToken, T> onUnknown) {this.onUnknown = requireNonNull(onUnknown);
return this;
}
public RedisTokenVisitor<T> build() {
return new LambdaRedisTokenVisitor<>(safe(onArray), safe(onStatus), safe(onString),
safe(onError), safe(onInteger), safe(onUnknown));
}
private <X> Function<X, T> safe(Function<X, T> function) {return nonNull(function) ? function : x -> null;
}
}
}
- LambdaRedisTokenVisitor 实现了 RedisTokenVisitor 接口,其结构器要求输出 onArray、onStatus、onString、onError、onInteger、onUnknown 这几个 Function
RedisSerializer
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/protocol/RedisSerializer.java
public class RedisSerializer {
private static final byte ARRAY = '*';
private static final byte ERROR = '-';
private static final byte INTEGER = ':';
private static final byte SIMPLE_STRING = '+';
private static final byte BULK_STRING = '$';
private static final byte[] DELIMITER = new byte[] {'\r', '\n'};
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private ByteBufferBuilder builder = new ByteBufferBuilder();
public byte[] encodeToken(RedisToken msg) {msg.accept(new AbstractRedisTokenVisitor<Void>() {
@Override
public Void string(StringRedisToken token) {addBulkStr(token.getValue());
return null;
}
@Override
public Void status(StatusRedisToken token) {addSimpleStr(token.getValue());
return null;
}
@Override
public Void integer(IntegerRedisToken token) {addInt(token.getValue());
return null;
}
@Override
public Void error(ErrorRedisToken token) {addError(token.getValue());
return null;
}
@Override
public Void array(ArrayRedisToken token) {addArray(token.getValue());
return null;
}
});
return builder.build();}
private void addBulkStr(SafeString str) {if (str != null) {builder.append(BULK_STRING).append(str.length()).append(DELIMITER).append(str);
} else {builder.append(BULK_STRING).append(-1);
}
builder.append(DELIMITER);
}
private void addSimpleStr(String str) {builder.append(SIMPLE_STRING).append(str.getBytes()).append(DELIMITER);
}
private void addInt(Integer value) {builder.append(INTEGER).append(value).append(DELIMITER);
}
private void addError(String str) {builder.append(ERROR).append(str.getBytes()).append(DELIMITER);
}
private void addArray(Sequence<RedisToken> array) {if (array != null) {builder.append(ARRAY).append(array.size()).append(DELIMITER);
for (RedisToken token : array) {builder.append(new RedisSerializer().encodeToken(token));
}
} else {builder.append(ARRAY).append(0).append(DELIMITER);
}
}
private static class ByteBufferBuilder {
private static final int INITIAL_CAPACITY = 1024;
private ByteBuffer buffer = ByteBuffer.allocate(INITIAL_CAPACITY);
private ByteBufferBuilder append(int i) {append(String.valueOf(i));
return this;
}
private ByteBufferBuilder append(String str) {append(str.getBytes(DEFAULT_CHARSET));
return this;
}
private ByteBufferBuilder append(SafeString str) {append(str.getBytes());
return this;
}
private ByteBufferBuilder append(byte[] buf) {ensureCapacity(buf.length);
buffer.put(buf);
return this;
}
public ByteBufferBuilder append(byte b) {ensureCapacity(1);
buffer.put(b);
return this;
}
private void ensureCapacity(int len) {if (buffer.remaining() < len) {growBuffer(len);
}
}
private void growBuffer(int len) {int capacity = buffer.capacity() + Math.max(len, INITIAL_CAPACITY);
buffer = ByteBuffer.allocate(capacity).put(build());
}
public byte[] build() {byte[] array = new byte[buffer.position()];
buffer.rewind();
buffer.get(array);
return array;
}
}
}
- RedisSerializer 的 encodeToken 办法创立了匿名 AbstractRedisTokenVisitor;其 string 办法执行 addBulkStr(token.getValue());其 status 办法执行 addSimpleStr(token.getValue());其 integer 办法执行 addInt(token.getValue());其 error 办法执行 addError(token.getValue());其 array 办法执行 addArray(token.getValue())
小结
RedisTokenVisitor 接口定义了 array、status、string、integer、error、unknown 办法,并提供了动态 builder 办法用于创立 LambdaRedisTokenVisitor.Builder;目前 RedisSerializer 的 encodeToken 办法创立了匿名 AbstractRedisTokenVisitor,提供了一个实现。不过目前这个接口的设计有点坏滋味,实践上应该把差别提取到泛型中。
doc
- RedisTokenVisitor