Inhaltsverzeichnis
Befehlssyntax festlegen
语法分析
代码设计
POINT数据类型
( OBJECT geojson)|(POINT lat lon z)|(BOUNDS minlat minlon maxlat maxlon)|(HASH geohash)|(STRING value)
Heim Java javaLernprogramm So implementieren Sie den Set-Befehl des in Springboot integrierten Tile-Clients

So implementieren Sie den Set-Befehl des in Springboot integrierten Tile-Clients

May 19, 2023 pm 01:37 PM
set springboot tile

    Befehlssyntax festlegen

    SET-Tasten-ID [Feldname-Wert ...] [EX-Sekunden] [NX|XX] (OBJECT geojson)|(POINT lat lon z)|(BOUNDS minlat minlon maxlat maxlon)|(HASH geohash)|(STRING value)

    set Der Befehl entspricht der Verwendung des Befehls hash in Redis. Er ist ebenfalls eine Kombination aus key und id, aber Der Unterschied besteht darin, dass der Befehl set von Tile38 auch weitere andere Attribute enthalten kann, z. B. das Anpassen des Felds FIELD und das Festlegen des Gültigkeitszeitraums von EX usw ., dann müssen wir eine nützliche Java-API für diese Syntax entwerfen, damit Entwickler Tile38 besser nutzen können. set命令就相当于redis中的hash命令的使用,也是一个keyid的组合,但是不同的是,Tile38的set命令还可以携带更多的其他属性,比如可以自定义FIELD字段,还可以设置EX有效期等等,那么我们需要给这个语法设计一套好用的java api,以便开发人员可以更好地使用Tile38。

    语法分析

    首先,根据上面提供的语法,我们可以分为三部分:

    1.第一部分就是命令的启示关键字SET,我们把这个关键字单独作为一部分;

    2.第二部分就是key id [FIELD name value ...] [EX seconds] [NX|XX],我们把这些都作为参数;

    3.第三部分就是最后的目标数据对象:

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

    代码设计

    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;
        }
    }
    Nach dem Login kopieren

    因为redis客户端工具在发送命令前需要对所有命令进行编码,所以要求所有的命令都必须实现ProtocolKeyword接口。如果命令的起始关键字是两个或多个单词,那么我们会使用下划线连接,转换成bytes的时候我们可以使用空格把下划线替换。

    2.我们把命令的第二部分抽象成一个具体的class,通过相关的字段来进行描述:

    public class SetOpts {
      private String key;
      private String id;
      //字段值必须是双精度浮点型
      private Map<String, Double> 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<String> commandLine() {
        List<String> result = new LinkedList<>();
        result.add(this.key);
        result.add(this.id);
        // 添加所有的FIELD
        if (MapUtils.isNotEmpty(this.fields)) {
          for (Map.Entry<String, Double> entry : this.fields.entrySet()) {
            result.add("FIELD");
            result.add(entry.getKey());
            result.add(entry.getValue().toString());
          }
        }
        // 添加`EX`
        if (this.ex >= 0) {
          result.add("EX");
          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<String, Double> 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<>();
          }
          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, "key is empty");
          }
          if (StringUtils.isEmpty(this.id)) {
            throw new AwesomeException(500, "id is empty");
          }
          // 创建SetOpts对象
          return new SetOpts(this);
        }
      }
    }
    Nach dem Login kopieren

    我们上面通过建造者的设计模式,把所有的参数都转换成了SetOpts这个类当中,开发人员就可以通过SetOpts对象的构建来灵活地控制命令中的参数了。

    3.我们需要把第三部分当中的不同数据对象转换成不同的类型:

    POINT数据类型

    Point关键的字段就是经纬度,除此之外,还有一个额外的字段z

    Grammatikanalyse

    Zunächst können wir es gemäß der oben bereitgestellten Grammatik in drei Teile unterteilen:

    1. Der erste Teil ist der Schlüssel zur Offenbarung des Befehls Word SET, wir nehmen dieses Schlüsselwort als separaten Teil

    2. Der zweite Teil ist key id [FIELD name value ...] [EX seconds] [NX|XX], wir verwenden diese als Parameter;

    3 🎜🎜#

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

    Codedesign

    1. Wir verwalten die Befehlsschlüsselwörter im ersten Teil durch Aufzählung:

    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;
      }
    }
    Nach dem Login kopieren

    Da das Redis-Client-Tool alle Befehle vor dem Senden codieren muss, müssen alle Befehle implementiert werden die ProtocolKeyword-Schnittstelle. Wenn das Startschlüsselwort des Befehls aus zwei oder mehr Wörtern besteht, verwenden wir Unterstriche, um sie zu verbinden. Bei der Konvertierung in Bytes können wir die Unterstriche durch Leerzeichen ersetzen.

    2. Wir abstrahieren den zweiten Teil des Befehls in eine bestimmte Klasse und beschreiben ihn durch verwandte Felder:

    @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;
      }
    }
    Nach dem Login kopieren

    Wir haben das Designmuster des Builders oben verwendet, nachdem alle Parameter vorhanden sind In die SetOpts-Klasse konvertiert, können Entwickler die Parameter im Befehl durch die Konstruktion von SetOpts-Objekten flexibel steuern.

    3. Wir müssen die verschiedenen Datenobjekte im dritten Teil in verschiedene Typen konvertieren:

    POINT-Datentyp#🎜🎜##🎜🎜#Punktschlüsselfelder Es ist Darüber hinaus gibt es ein zusätzliches Feld z, das zur Speicherung zusätzlicher Geschäftsparameter verwendet wird und leer sein kann. #🎜🎜#
    @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;
      }
    }
    Nach dem Login kopieren
    #🎜🎜#BOUNDS-Datentyp#🎜🎜##🎜🎜#BOUNDS ist ein Rechteck. Seine Schlüsselfelder sind die untere linke Ecke und die obere rechte Ecke und Obere rechte Ecke; #🎜🎜#
    Point,
    LineString,
    Polygon,
    MultiPoint,
    MultiLineString,
    MultiPolygon
    Nach dem Login kopieren
    #🎜🎜#HASH- und STRING-Datentypen#🎜🎜##🎜🎜#HASH und STRING sind eigentlich eine separate Zeichenfolge, aber wir kapseln sie trotzdem, damit Entwickler sie verwenden können;# 🎜🎜#
    @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();
        }
      }
    }
    Nach dem Login kopieren
    #🎜🎜#OBJECT-Datentyp#🎜🎜##🎜🎜#OBJECT ist eigentlich GeoJSON-Daten. Es gibt insgesamt sechs Typen, die mehr wissen möchten. org /#🎜🎜#
    // 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
        }
      }
    Nach dem Login kopieren
    #🎜🎜#Damit Entwickler diese sechs Typen besser nutzen können, verwenden wir auch das Builder-Muster, um den GeoJSON-Datentyp zu entwerfen: #🎜🎜#
    public abstract class Element implements Serializable {
      public abstract List<String> commandArgs();
    }
    Nach dem Login kopieren
    #🎜🎜#Wir haben jetzt eine große Kategorie Darin werden mehrere Methoden erstellt, und jede Methode erstellt einen Builder des entsprechenden Typs. In diesem Fall entspricht dies sechs Möglichkeiten zum Erstellen von Objekten in dieser Klasse, und jeder Builder ist nur für die Erstellung des entsprechenden Objekts verantwortlich. #🎜🎜##🎜🎜#Das Folgende sind die Codes der sechs Builder. Jedes Objekt basiert auf dem grundlegendsten BaseGeoJson. Der öffentliche Feldtyp und zusätzliche Metafelder werden aus BaseGeoJson extrahiert und die Ebene der Koordinatenpunkte sind unterschiedlich, daher ist das Codedesign je nach den Merkmalen jedes Typs wie folgt: #🎜🎜#
    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);
      }
    Nach dem Login kopieren
    #🎜🎜#Fügen Sie abschließend ein Basisklassenelement hinzu: #🎜🎜#rrreee#🎜🎜# Verwendung# 🎜🎜##🎜🎜#Wir konvertieren alle Datentypen in spezifische Codedesigns. Sehen wir uns an, wie man sie verwendet: #🎜🎜#rrreee

    Das obige ist der detaillierte Inhalt vonSo implementieren Sie den Set-Befehl des in Springboot integrierten Tile-Clients. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Erklärung dieser Website
    Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

    Heiße KI -Werkzeuge

    Undresser.AI Undress

    Undresser.AI Undress

    KI-gestützte App zum Erstellen realistischer Aktfotos

    AI Clothes Remover

    AI Clothes Remover

    Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

    Undress AI Tool

    Undress AI Tool

    Ausziehbilder kostenlos

    Clothoff.io

    Clothoff.io

    KI-Kleiderentferner

    AI Hentai Generator

    AI Hentai Generator

    Erstellen Sie kostenlos Ai Hentai.

    Heißer Artikel

    R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
    3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O. Beste grafische Einstellungen
    3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
    3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
    WWE 2K25: Wie man alles in Myrise freischaltet
    4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

    Heiße Werkzeuge

    Notepad++7.3.1

    Notepad++7.3.1

    Einfach zu bedienender und kostenloser Code-Editor

    SublimeText3 chinesische Version

    SublimeText3 chinesische Version

    Chinesische Version, sehr einfach zu bedienen

    Senden Sie Studio 13.0.1

    Senden Sie Studio 13.0.1

    Leistungsstarke integrierte PHP-Entwicklungsumgebung

    Dreamweaver CS6

    Dreamweaver CS6

    Visuelle Webentwicklungstools

    SublimeText3 Mac-Version

    SublimeText3 Mac-Version

    Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

    Wie Springboot Jasypt integriert, um die Verschlüsselung von Konfigurationsdateien zu implementieren Wie Springboot Jasypt integriert, um die Verschlüsselung von Konfigurationsdateien zu implementieren Jun 01, 2023 am 08:55 AM

    Einführung in Jasypt Jasypt ist eine Java-Bibliothek, die es einem Entwickler ermöglicht, seinem Projekt mit minimalem Aufwand grundlegende Verschlüsselungsfunktionen hinzuzufügen und kein tiefes Verständnis der Funktionsweise der Verschlüsselung erfordert. standardbasierte Verschlüsselungstechnologie. Passwörter, Text, Zahlen, Binärdateien verschlüsseln ... Geeignet für die Integration in Spring-basierte Anwendungen, offene API, zur Verwendung mit jedem JCE-Anbieter ... Fügen Sie die folgende Abhängigkeit hinzu: com.github.ulisesbocchiojasypt-spring-boot-starter2 Die Vorteile von Jasypt schützen unsere Systemsicherheit. Selbst wenn der Code durchgesickert ist, kann die Datenquelle garantiert werden.

    Ausführliche Erläuterung der Funktion „Tag festlegen' in den dynamischen SQL-Tags von MyBatis Ausführliche Erläuterung der Funktion „Tag festlegen' in den dynamischen SQL-Tags von MyBatis Feb 26, 2024 pm 07:48 PM

    Interpretation der dynamischen SQL-Tags von MyBatis: Detaillierte Erläuterung der Verwendung von Set-Tags. MyBatis ist ein hervorragendes Persistenzschicht-Framework. Es bietet eine Fülle dynamischer SQL-Tags und kann Datenbankoperationsanweisungen flexibel erstellen. Unter anderem wird das Set-Tag zum Generieren der SET-Klausel in der UPDATE-Anweisung verwendet, die sehr häufig bei Aktualisierungsvorgängen verwendet wird. In diesem Artikel wird die Verwendung des Set-Tags in MyBatis ausführlich erläutert und seine Funktionalität anhand spezifischer Codebeispiele demonstriert. Was ist Set-Tag? Set-Tag wird in MyBati verwendet

    Wie SpringBoot Redisson integriert, um eine Verzögerungswarteschlange zu implementieren Wie SpringBoot Redisson integriert, um eine Verzögerungswarteschlange zu implementieren May 30, 2023 pm 02:40 PM

    Nutzungsszenario 1. Die Bestellung wurde erfolgreich aufgegeben, die Zahlung erfolgte jedoch nicht innerhalb von 30 Minuten. Die Zahlung ist abgelaufen und die Bestellung wurde automatisch storniert. 2. Die Bestellung wurde unterzeichnet und es wurde 7 Tage lang keine Bewertung durchgeführt. Wenn die Bestellung abläuft und nicht ausgewertet wird, wird die Bestellung standardmäßig positiv bewertet. Wenn der Händler die Bestellung innerhalb von 5 Minuten nicht erhält, wird die Bestellung abgebrochen Es wird eine SMS-Erinnerung gesendet ... Für Szenarien mit langen Verzögerungen und geringer Echtzeitleistung können wir die Aufgabenplanung verwenden, um eine regelmäßige Abfrageverarbeitung durchzuführen. Zum Beispiel: xxl-job Heute werden wir auswählen

    So implementieren Sie verteilte Sperren mit Redis in SpringBoot So implementieren Sie verteilte Sperren mit Redis in SpringBoot Jun 03, 2023 am 08:16 AM

    1. Redis implementiert das Prinzip der verteilten Sperren und warum verteilte Sperren erforderlich sind. Bevor über verteilte Sperren gesprochen wird, muss erläutert werden, warum verteilte Sperren erforderlich sind. Das Gegenteil von verteilten Sperren sind eigenständige Sperren. Wenn wir Multithread-Programme schreiben, vermeiden wir Datenprobleme, die durch den gleichzeitigen Betrieb einer gemeinsam genutzten Variablen verursacht werden. Normalerweise verwenden wir eine Sperre, um die Richtigkeit der gemeinsam genutzten Variablen sicherzustellen Die gemeinsam genutzten Variablen liegen im gleichen Prozess. Wenn es mehrere Prozesse gibt, die gleichzeitig eine gemeinsam genutzte Ressource betreiben müssen, wie können sie sich dann gegenseitig ausschließen? Heutige Geschäftsanwendungen sind in der Regel Microservice-Architekturen, was auch bedeutet, dass eine Anwendung mehrere Prozesse bereitstellen muss. Wenn mehrere Prozesse dieselbe Datensatzzeile in MySQL ändern müssen, ist eine Verteilung erforderlich, um fehlerhafte Daten zu vermeiden wird zu diesem Zeitpunkt eingeführt. Der Stil ist gesperrt. Punkte erreichen wollen

    So lösen Sie das Problem, dass Springboot nach dem Einlesen in ein JAR-Paket nicht auf die Datei zugreifen kann So lösen Sie das Problem, dass Springboot nach dem Einlesen in ein JAR-Paket nicht auf die Datei zugreifen kann Jun 03, 2023 pm 04:38 PM

    Springboot liest die Datei, kann aber nach dem Packen in ein JAR-Paket nicht auf die neueste Entwicklung zugreifen. Es gibt eine Situation, in der Springboot die Datei nach dem Packen in ein JAR-Paket nicht lesen kann ist ungültig und kann nur über den Stream gelesen werden. Die Datei befindet sich unter resources publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

    Vergleich und Differenzanalyse zwischen SpringBoot und SpringMVC Vergleich und Differenzanalyse zwischen SpringBoot und SpringMVC Dec 29, 2023 am 11:02 AM

    SpringBoot und SpringMVC sind beide häufig verwendete Frameworks in der Java-Entwicklung, es gibt jedoch einige offensichtliche Unterschiede zwischen ihnen. In diesem Artikel werden die Funktionen und Verwendungsmöglichkeiten dieser beiden Frameworks untersucht und ihre Unterschiede verglichen. Lassen Sie uns zunächst etwas über SpringBoot lernen. SpringBoot wurde vom Pivotal-Team entwickelt, um die Erstellung und Bereitstellung von Anwendungen auf Basis des Spring-Frameworks zu vereinfachen. Es bietet eine schnelle und einfache Möglichkeit, eigenständige, ausführbare Dateien zu erstellen

    So implementieren Sie Springboot+Mybatis-plus, ohne SQL-Anweisungen zum Hinzufügen mehrerer Tabellen zu verwenden So implementieren Sie Springboot+Mybatis-plus, ohne SQL-Anweisungen zum Hinzufügen mehrerer Tabellen zu verwenden Jun 02, 2023 am 11:07 AM

    Wenn Springboot + Mybatis-plus keine SQL-Anweisungen zum Hinzufügen mehrerer Tabellen verwendet, werden die Probleme, auf die ich gestoßen bin, durch die Simulation des Denkens in der Testumgebung zerlegt: Erstellen Sie ein BrandDTO-Objekt mit Parametern, um die Übergabe von Parametern an den Hintergrund zu simulieren dass es äußerst schwierig ist, Multi-Table-Operationen in Mybatis-plus durchzuführen. Wenn Sie keine Tools wie Mybatis-plus-join verwenden, können Sie nur die entsprechende Mapper.xml-Datei konfigurieren und die stinkende und lange ResultMap konfigurieren Schreiben Sie die entsprechende SQL-Anweisung. Obwohl diese Methode umständlich erscheint, ist sie äußerst flexibel und ermöglicht es uns

    Wie SpringBoot Redis anpasst, um die Cache-Serialisierung zu implementieren Wie SpringBoot Redis anpasst, um die Cache-Serialisierung zu implementieren Jun 03, 2023 am 11:32 AM

    1. Passen Sie den RedisTemplate1.1-Standard-Serialisierungsmechanismus an. Die API-basierte Redis-Cache-Implementierung verwendet die RedisTemplate-Vorlage für Daten-Caching-Vorgänge. Öffnen Sie hier die RedisTemplate-Klasse und zeigen Sie die Quellcodeinformationen der Klasse publicclassRedisTemplateextendsRedisAccessorimplementsRedisOperations an. Schlüssel deklarieren, verschiedene Serialisierungsmethoden des Werts, der Anfangswert ist leer @NullableprivateRedisSe

    See all articles