ホームページ >Java >&#&チュートリアル >Springboot統合タイルクライアントのSetコマンドの実装方法

Springboot統合タイルクライアントのSetコマンドの実装方法

王林
王林転載
2023-05-19 13:37:101422ブラウズ

    set コマンド構文

    SET キー ID [フィールド名 値 ...] [EX 秒] [NX|XX] (OBJECT geojson )|(POINT lat lon z)|(BOUNDS minlat minlon maxlat maxlon)|(HASH geohash)|(STRING 値)

    #set コマンドは、redis の # と同等です。 ##hash コマンドの keyid の組み合わせでもありますが、違いは、Tile38 の set コマンドは、より多くのその他の属性も保持できることです。 FIELD フィールドのカスタマイズや EX 有効期間の設定など、この構文に役立つ java api## を設計する必要があります。開発者が Tile38 をより適切に使用できるようになります。 文法分析

    まず第一に、上記の文法に従って、それを 3 つの部分に分けることができます:

    1. 最初の部分は、次の啓示のキーワードです。 command

    SET

    、このキーワードを別個の部分として扱います;

    2. 2 番目の部分は key id [FIELD name value ...] [EX 秒] [NX| XX]

    、これらをパラメータとして受け取ります;

    3. 3 番目の部分は、最終的なターゲット データ オブジェクトです:

    (OBJECT geojson)|(POINT lat lon z) |(BOUNDS minlat minlon maxlat maxlon)|(HASH geohash)|(STRING 値)

    コード設計

    1. コマンド キーワードの最初の部分は列挙によって管理します。 # #
    enum Tile38Command implements ProtocolKeyword {
        SET;
        public final byte[] bytes;
        static final String UNDERSCORE = "_";
        static final String SPACE = " ";
        Tile38Command() {
          String name = StringUtils.replace(this.name(), UNDERSCORE, SPACE);
          this.bytes = name.getBytes(StandardCharsets.US_ASCII);
        }
        @Override
        public byte[] getBytes() {
          return this.bytes;
        }
    }

    Redis クライアント ツールは送信前にすべてのコマンドをエンコードする必要があるため、すべてのコマンドは

    ProtocolKeyword

    インターフェイスを実装する必要があります。コマンドの開始キーワードが 2 つ以上の単語の場合は、それらをアンダースコアで接続します。バイトに変換する場合は、アンダースコアをスペースで置き換えることができます。

    2. コマンドの 2 番目の部分を特定のクラスに抽象化し、関連フィールドを通じてそれを記述します: <pre class="brush:java;">public class SetOpts { private String key; private String id; //字段值必须是双精度浮点型 private Map&lt;String, Double&gt; fields; // 单位秒 private int ex; // 创建方式: // NX 不存在的时候创建 // XX 存在的时候更新 private NxXx nxXx; private SetOpts(Builder builder) { this.key = builder.key; this.id = builder.id; this.fields = builder.fields; this.ex = builder.ex; this.nxXx = builder.nxXx; } // 把所有的参数按顺序放到列表中 public List&lt;String&gt; commandLine() { List&lt;String&gt; result = new LinkedList&lt;&gt;(); result.add(this.key); result.add(this.id); // 添加所有的FIELD if (MapUtils.isNotEmpty(this.fields)) { for (Map.Entry&lt;String, Double&gt; entry : this.fields.entrySet()) { result.add(&quot;FIELD&quot;); result.add(entry.getKey()); result.add(entry.getValue().toString()); } } // 添加`EX` if (this.ex &gt;= 0) { result.add(&quot;EX&quot;); result.add(String.valueOf(this.ex)); } // 添加NX或XX if (Objects.nonNull(this.nxXx)) { result.add(this.nxXx.name()); } // 返回结果 return result; } public enum NxXx { NX, XX } // 建造者模式 public static class Builder { private String key; private String id; //字段值必须是双精度浮点型 private Map&lt;String, Double&gt; fields; // 单位秒 private int ex = -1; // 创建方式: // NX 不存在的时候创建 // XX 存在的时候更新 private NxXx nxXx; public Builder key(String key) { this.key = key; return this; } public Builder id(String id) { this.id = id; return this; } public Builder field(String field, double value) { if (Objects.isNull(this.fields)) { this.fields = new LinkedHashMap&lt;&gt;(); } this.fields.put(field, value); return this; } public Builder ex(int seconds) { this.ex = seconds; return this; } public Builder nxXx(NxXx nxXx) { this.nxXx = nxXx; return this; } public SetOpts build() throws AwesomeException { if (StringUtils.isEmpty(this.key)) { throw new AwesomeException(500, &quot;key is empty&quot;); } if (StringUtils.isEmpty(this.id)) { throw new AwesomeException(500, &quot;id is empty&quot;); } // 创建SetOpts对象 return new SetOpts(this); } } }</pre> 上記では、ビルダーの設計モードを使用してすべてのパラメータを配置します。 SetOpts クラスを使用すると、開発者は SetOpts オブジェクトの構築を通じてコマンド内のパラメーターを柔軟に制御できます。

    3. 3 番目の部分のさまざまなデータ オブジェクトをさまざまなタイプに変換する必要があります:

    POINT データ型

    Point のキー フィールドは経度と緯度です。さらに、追加フィールド

    z

    があり、これは追加のビジネス パラメーターを保存するために使用され、空にすることができます。

    public class Point extends Element implements Serializable {
      // 经度
      private double lng;
      // 维度
      private double lat;
      // 额外的数据
      private double z;
      public Point(double lng, double lat, double z) {
        this.lat = lat;
        this.lng = lng;
        this.z = z;
      }
      public Point(double lng, double lat) {
        this(lng, lat, Integer.MIN_VALUE);
      }
      @Override
      public List<String> commandArgs() {
        List<String> result = new LinkedList<>();
        result.add("POINT");
        result.add(String.valueOf(this.lng));
        result.add(String.valueOf(this.lat));
        if (this.z != Integer.MIN_VALUE) {
          result.add(String.valueOf(this.z));
        }
        return result;
      }
    }

    BOUNDS データ型BOUNDS は長方形であり、そのキー フィールドは左下隅と右上隅です。左下隅と右上隅を表すには、座標 1 と座標 2 を使用します。 ;

    @AllArgsConstructor
    public class Bounds extends Element {
      private double[] coordinate1;
      private double[] coordinate2;
      @Override
      public List<String> commandArgs() {
        List<String> result = new LinkedList<>();
        result.add("BOUNDS");
        result.add(String.valueOf(coordinate1[0]));
        result.add(String.valueOf(coordinate1[1]));
        result.add(String.valueOf(coordinate2[0]));
        result.add(String.valueOf(coordinate2[1]));
        return result;
      }
    }

    HASH および STRING データ型

    HASH と STRING は実際には別の文字列ですが、開発者が使用できるようにカプセル化しています;

    @AllArgsConstructor
    public class Geohash extends Element {
      private String hash;
      @Override
      public List<String> commandArgs() {
        List<String> result = new LinkedList<>();
        result.add("HASH");
        result.add(this.hash);
        return result;
      }
    }
    @AllArgsConstructor
    public class RawString extends Element {
      private String raw;
      @Override
      public List<String> commandArgs() {
        List<String> result = new LinkedList<>();
        result.add("STRING");
        result.add(this.raw);
        return result;
      }
    }

    OBJECT データ型

    OBJECT は実際には GeoJSON データです。このタイプのデータは少し複雑です。全部で 6 つのタイプがあります。詳しく知りたい方は、ここを参照してください。 geojson.org/

    Point,
    LineString,
    Polygon,
    MultiPoint,
    MultiLineString,
    MultiPolygon

    In order forこれら 6 つのタイプをより効果的に使用するために、ビルダー パターンを使用して GeoJSON データ タイプも設計します。

    @Data
    public class GeoJson {
      public static class Builder {
        public Point.Builder point() {
          return new Point.Builder();
        }
        public MultiPoint.Builder multPoint() {
          return new MultiPoint.Builder();
        }
        public LineString.Builder lineString() {
          return new LineString.Builder();
        }
        public MultiLineString.Builder multiLineString() {
          return new MultiLineString.Builder();
        }
        public Polygon.Builder polygon() {
          return new Polygon.Builder();
        }
        public MultiPolygon.Builder multiPolygon() {
          return new MultiPolygon.Builder();
        }
      }
    }

    ここで、大きなクラスに複数のメソッドを作成し、各メソッドに対応するタイプのビルダーを配置します。この場合、これは、このクラスでオブジェクトを作成する方法が 6 つあることと同等であり、各ビルダーは対応するオブジェクトを構築することのみを担当します。

    以下は 6 つのビルダーのコードです。各オブジェクトは最も基本的な BaseGeoJson に基づいて構築されています。パブリック フィールド タイプと追加のメタ フィールドは BaseGeoJson から抽出されます。各タイプの違いは座標にあります。ポイントの数やレベルが異なるため、それぞれのタイプの特性に応じて、次のようなコード設計になります。

    // Point类型
      public static class Point extends BaseGeoJson {
        // 坐标点
        private double[] coordinates;
        Point(Builder builder) {
          super(builder);
          this.type = GeoJsonType.Point;
          this.coordinates = builder.coordinates;
        }
        @Override
        protected Object coordinates() {
          return this.coordinates;
        }
        public static class Builder extends BaseGeoJson.Builder {
          private double[] coordinates;
          public Builder coordinate(double lon, double lat) {
            coordinates = new double[]{lat, lon};
            return this;
          }
          public Point build() {
            return new Point(this);
          }
        }
      }
    // MultiPoint类型
      public static class MultiPoint extends BaseGeoJson {
        private double[][] coordinates;
        MultiPoint(Builder builder) {
          super(builder);
          this.type = GeoJsonType.MultiPoint;
          this.coordinates = builder.convert2Array();
        }
        @Override
        protected Object coordinates() {
          return this.coordinates;
        }
        public static class Builder extends BaseGeoJson.Builder {
          private List<Coordinate> coordinates;
          public Builder coordinate(double lon, double lat) {
            if (CollectionUtils.isEmpty(this.coordinates)) {
              this.coordinates = new LinkedList<>();
            }
            this.coordinates.add(new Coordinate(lat, lon));
            return this;
          }
          protected double[][] convert2Array() {
            int length = this.coordinates.size();
            double[][] result = new double[length][];
            for (int i = 0; i < length; i++) {
              result[i] = this.coordinates.get(i).convertToArray();
            }
            return result;
          }
          @Override
          public MultiPoint build() {
            return new MultiPoint(this);
          }
        }
      }
    // LineString类型
      public static class LineString extends MultiPoint {
        private double[][] coordinates;
        LineString(Builder builder) {
          super(builder);
          this.type = GeoJsonType.LineString;
        }
        public static class Builder extends MultiPoint.Builder {
          @Override
          public LineString build() {
            return new LineString(this);
          }
        }
      }
    // MultiLineString类型
      public static class MultiLineString extends BaseGeoJson {
        private double[][][] coordinates;
        MultiLineString(Builder builder) {
          super(builder);
          this.type = GeoJsonType.MultiLineString;
          this.coordinates = builder.convertToArray();
        }
        @Override
        protected Object coordinates() {
          return this.coordinates;
        }
        public static class Builder extends BaseGeoJson.Builder {
          private List<Line> lines = new LinkedList<>();
          public Line line() {
            return new Line(this);
          }
          void addLine(Line line) {
            lines.add(line);
          }
          double[][][] convertToArray() {
            int length = this.lines.size();
            double[][][] result = new double[length][][];
            for (int i = 0; i < length; i++) {
              Line line = this.lines.get(i);
              result[i] = line.convert2Array();
            }
            return result;
          }
          @Override
          public BaseGeoJson build() {
            return new MultiLineString(this);
          }
        }
        static class Line {
          private List<Coordinate> coordinates;
          private Builder builder;
          Line(Builder builder) {
            this.builder = builder;
            this.builder.addLine(this);
          }
          private double[][] convert2Array() {
            int length = this.coordinates.size();
            double[][] result = new double[length][];
            for (int i = 0; i < length; i++) {
              result[i] = this.coordinates.get(i).convertToArray();
            }
            return result;
          }
          public Line coordinate(double lon, double lat) {
            if (CollectionUtils.isEmpty(this.coordinates)) {
              this.coordinates = new LinkedList<>();
            }
            this.coordinates.add(new Coordinate(lat, lon));
            return this;
          }
          public Line nextLine() {
            return new Line(this.builder);
          }
          public Builder end() {
            return this.builder;
          }
        }
      }
    // Polygon类型
      public static class Polygon extends MultiPoint {
        private double[][][] coordinates;
        Polygon(Builder builder) {
          super(builder);
          this.type = GeoJsonType.Polygon;
          this.coordinates = new double[][][]{builder.convert2Array()};
        }
        public static class Builder extends MultiPoint.Builder {
          @Override
          public Polygon build() {
            return new Polygon(this);
          }
        }
      }
    // MultiPolygon类型
      public static class MultiPolygon extends BaseGeoJson {
        private double[][][][] coordinates;
        MultiPolygon(Builder builder) {
          super(builder);
          this.type = GeoJsonType.MultiPolygon;
          this.coordinates = new double[][][][]{builder.convert2Array()};
        }
        @Override
        protected Object coordinates() {
          return this.coordinates;
        }
        public static class Builder extends BaseGeoJson.Builder {
          private List<Polygon> polygons = new LinkedList<>();
          @Override
          public BaseGeoJson build() {
            return new MultiPolygon(this);
          }
          void addPolygon(Polygon polygon) {
            polygons.add(polygon);
          }
          private double[][][] convert2Array() {
            int length = this.polygons.size();
            double[][][] result = new double[length][][];
            for (int i = 0; i < length; i++) {
              result[i] = this.polygons.get(i).convert2Array();
            }
            return result;
          }
        }
        static class Polygon {
          private List<Coordinate> coordinates;
          private Builder builder;
          Polygon(Builder builder) {
            this.builder = builder;
            this.builder.addPolygon(this);
          }
          private double[][] convert2Array() {
            int length = this.coordinates.size();
            double[][] result = new double[length][];
            for (int i = 0; i < length; i++) {
              result[i] = this.coordinates.get(i).convertToArray();
            }
            return result;
          }
          public Polygon coordinate(double lon, double lat) {
            if (CollectionUtils.isEmpty(this.coordinates)) {
              this.coordinates = new LinkedList<>();
            }
            this.coordinates.add(new Coordinate(lat, lon));
            return this;
          }
          public Polygon nextLine() {
            return new Polygon(this.builder);
          }
          public Builder end() {
            return this.builder;
          }
        }
      }
    // 基类BaseGeoJson
      public abstract static class BaseGeoJson extends Element {
        // 公共字段type
        protected GeoJsonType type;
        // 公共字段metadata
        private Map<String, String> metadata;
        BaseGeoJson(Builder builder) {
          this.metadata = builder.metadata;
        }
        protected abstract Object coordinates();
        // 转换成命令参数
        @Override
        public List<String> commandArgs() {
          List<String> result = new LinkedList<>();
          result.add("OBJECT");
          result.add(toJson());
          return result;
        }
        // 提供统一的转json方法
        protected String toJson() {
          Map<String, Object> map = new LinkedHashMap<>();
          map.put("type", this.type);
          map.put("coordinates", coordinates());
          if (!CollectionUtils.isEmpty(this.metadata)) {
            for (Map.Entry<String, String> entry : this.metadata.entrySet()) {
              map.put(entry.getKey(), entry.getValue());
            }
          }
          return JsonUtil.obj2String(map);
        }
        abstract static class Builder {
          private Map<String, String> metadata;
          public Builder meta(String key, String value) {
            if (MapUtils.isEmpty(this.metadata)) {
              this.metadata = new LinkedHashMap<>();
            }
            this.metadata.put(key, value);
            return this;
          }
          public abstract BaseGeoJson build();
        }
        static class Coordinate {
          private double lat;
          private double lon;
          Coordinate(double lat, double lon) {
            this.lat = lat;
            this.lon = lon;
          }
          public double[] convertToArray() {
            return new double[]{this.lat, this.lon};
          }
        }
        // GeoJSON所有的数据类型
        enum GeoJsonType {
          Point,
          LineString,
          Polygon,
          MultiPoint,
          MultiLineString,
          MultiPolygon
        }
      }

    最後に、基本クラスの要素を追加します。

    public abstract class Element implements Serializable {
      public abstract List<String> commandArgs();
    }

    使い方

    We All データ型は特定のコード設計に変換されます。使用方法を見てみましょう:

    private String setElement(SetOpts setOpts, Element element) {
        List<String> args1 = setOpts.commandLine();
        List<String> commandArgs = element.commandArgs();
        return execute(Tile38Command.SET, args1, commandArgs);
    }
    /**
       * 设置点位
       *
       * @param setOpts
       * @param point
       * @return
       */
      public String setPoint(SetOpts setOpts, Point point) {
        return setElement(setOpts, point);
      }
      /**
       * 设置对象
       *
       * @param setOpts
       * @param geoJson
       * @return
       */
      public String setObject(SetOpts setOpts, GeoJson.BaseGeoJson geoJson) {
        return setElement(setOpts, geoJson);
      }
      /**
       * 设置矩形边界
       *
       * @param setOpts
       * @param bounds
       * @return
       */
      public String setBounds(SetOpts setOpts, Bounds bounds) {
        return setElement(setOpts, bounds);
      }
      /**
       * 设置geohash
       *
       * @param setOpts
       * @param geohash
       * @return
       */
      public String setGeohash(SetOpts setOpts, Geohash geohash) {
        return setElement(setOpts, geohash);
      }
      /**
       * 设置String
       *
       * @param setOpts
       * @param string
       * @return
       */
      public String setString(SetOpts setOpts, RawString string) {
        return setElement(setOpts, string);
      }

    以上がSpringboot統合タイルクライアントのSetコマンドの実装方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。