本文次要钻研一下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