Table of Contents
set command syntax
z
Home Java javaTutorial How to implement the Set command of Springboot integrated Tile client

How to implement the Set command of Springboot integrated Tile client

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

    set command syntax

    SET key id [FIELD name value ...] [EX seconds] [NX|XX] (OBJECT geojson )|(POINT lat lon z)|(BOUNDS minlat minlon maxlat maxlon)|(HASH geohash)|(STRING value)

    ##set command is equivalent to # in redis The use of the ##hash command is also a combination of key and id, but the difference is that Tile38’s set command can also carry more Other attributes, such as customizing the FIELD field, and setting the EX validity period, etc., then we need to design a useful java api## for this syntax. # so that developers can better use Tile38. Grammar analysis

    First of all, according to the grammar provided above, we can divide it into three parts:

    1. The first part is the revelation keyword of the command

    SET

    , we take this keyword as a separate part;

    2. The second part is key id [FIELD name value ...] [EX seconds] [NX|XX]

    , We take these as parameters;

    3. The third part is the final target data object:

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

    Code design

    1. We manage the first part of the command keywords through enumeration:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    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;

        }

    }

    Copy after login

    Because the redis client tool needs to encode all commands before sending them, all commands must implement the

    ProtocolKeyword

    interface. If the starting keyword of the command is two or more words, then we will use underscores to connect them. When converting to bytes, we can use spaces to replace the underscores.

    2. We abstract the second part of the command into a specific class and describe it through related fields:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    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);

        }

      }

    }

    Copy after login

    We above use the builder's design mode to put all the parameters All are converted into the SetOpts class, and developers can flexibly control the parameters in the command through the construction of SetOpts objects.

    3. We need to convert the different data objects in the third part into different types:

    POINT data type

    The key field of Point is longitude and latitude, in addition In addition, there is an additional field

    z

    , which is used to store additional business parameters and can be empty.

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    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;

      }

    }

    Copy after login
    BOUNDS data type

    BOUNDS is a rectangle, and its key fields are the lower left corner and upper right corner. We use coordinate1 and coordinate2 to represent the lower left corner and upper right corner;

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    @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;

      }

    }

    Copy after login

    HASH and STRING data types

    HASH and STRING are actually a separate string, but we still encapsulate it for developers to use;

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    @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;

      }

    }

    Copy after login

    OBJECT data Type

    OBJECT is actually GeoJSON data. This type of data is a bit more complicated. There are six types in total. Friends who want to know more can see here geojson.org/

    1

    2

    3

    4

    5

    6

    Point,

    LineString,

    Polygon,

    MultiPoint,

    MultiLineString,

    MultiPolygon

    Copy after login

    In order for developers to To better use these six types, we also use the builder pattern to design the GeoJSON data type:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    @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();

        }

      }

    }

    Copy after login

    We now create multiple methods in a large class, and each method puts the builder of the corresponding type Created, in this case, it is equivalent to six ways of creating objects in this class, and each builder is only responsible for building the corresponding object.

    The following are the codes of the six builders. Each object is constructed based on the most basic BaseGeoJson. The public field type and additional meta fields are extracted from BaseGeoJson. The difference between each type lies in the coordinates. The number and level of points are different, so according to the characteristics of each type, the code design is as follows:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    97

    98

    99

    100

    101

    102

    103

    104

    105

    106

    107

    108

    109

    110

    111

    112

    113

    114

    115

    116

    117

    118

    119

    120

    121

    122

    123

    124

    125

    126

    127

    128

    129

    130

    131

    132

    133

    134

    135

    136

    137

    138

    139

    140

    141

    142

    143

    144

    145

    146

    147

    148

    149

    150

    151

    152

    153

    154

    155

    156

    157

    158

    159

    160

    161

    162

    163

    164

    165

    166

    167

    168

    169

    170

    171

    172

    173

    174

    175

    176

    177

    178

    179

    180

    181

    182

    183

    184

    185

    186

    187

    188

    189

    190

    191

    192

    193

    194

    195

    196

    197

    198

    199

    200

    201

    202

    203

    204

    205

    206

    207

    208

    209

    210

    211

    212

    213

    214

    215

    216

    217

    218

    219

    220

    221

    222

    223

    224

    225

    226

    227

    228

    229

    230

    231

    232

    233

    234

    235

    236

    237

    238

    239

    240

    241

    242

    243

    244

    245

    246

    247

    248

    249

    250

    251

    252

    253

    254

    255

    256

    257

    258

    259

    260

    261

    262

    263

    264

    265

    266

    267

    268

    269

    270

    271

    272

    273

    274

    // 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

        }

      }

    Copy after login

    Finally, add a base class Element:

    1

    2

    3

    public abstract class Element implements Serializable {

      public abstract List<String> commandArgs();

    }

    Copy after login

    How to use

    We All data types are converted into specific code designs. Let’s see how to use them:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    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);

      }

    Copy after login

    The above is the detailed content of How to implement the Set command of Springboot integrated Tile client. For more information, please follow other related articles on the PHP Chinese website!

    Statement of this Website
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

    Hot AI Tools

    Undresser.AI Undress

    Undresser.AI Undress

    AI-powered app for creating realistic nude photos

    AI Clothes Remover

    AI Clothes Remover

    Online AI tool for removing clothes from photos.

    Undress AI Tool

    Undress AI Tool

    Undress images for free

    Clothoff.io

    Clothoff.io

    AI clothes remover

    Video Face Swap

    Video Face Swap

    Swap faces in any video effortlessly with our completely free AI face swap tool!

    Hot Tools

    Notepad++7.3.1

    Notepad++7.3.1

    Easy-to-use and free code editor

    SublimeText3 Chinese version

    SublimeText3 Chinese version

    Chinese version, very easy to use

    Zend Studio 13.0.1

    Zend Studio 13.0.1

    Powerful PHP integrated development environment

    Dreamweaver CS6

    Dreamweaver CS6

    Visual web development tools

    SublimeText3 Mac version

    SublimeText3 Mac version

    God-level code editing software (SublimeText3)

    How Springboot integrates Jasypt to implement configuration file encryption How Springboot integrates Jasypt to implement configuration file encryption Jun 01, 2023 am 08:55 AM

    Introduction to Jasypt Jasypt is a java library that allows a developer to add basic encryption functionality to his/her project with minimal effort and does not require a deep understanding of how encryption works. High security for one-way and two-way encryption. , standards-based encryption technology. Encrypt passwords, text, numbers, binaries... Suitable for integration into Spring-based applications, open API, for use with any JCE provider... Add the following dependency: com.github.ulisesbocchiojasypt-spring-boot-starter2. 1.1Jasypt benefits protect our system security. Even if the code is leaked, the data source can be guaranteed.

    How SpringBoot integrates Redisson to implement delay queue How SpringBoot integrates Redisson to implement delay queue May 30, 2023 pm 02:40 PM

    Usage scenario 1. The order was placed successfully but the payment was not made within 30 minutes. The payment timed out and the order was automatically canceled. 2. The order was signed and no evaluation was conducted for 7 days after signing. If the order times out and is not evaluated, the system defaults to a positive rating. 3. The order is placed successfully. If the merchant does not receive the order for 5 minutes, the order is cancelled. 4. The delivery times out, and push SMS reminder... For scenarios with long delays and low real-time performance, we can Use task scheduling to perform regular polling processing. For example: xxl-job Today we will pick

    Detailed explanation of the Set tag function in MyBatis dynamic SQL tags Detailed explanation of the Set tag function in MyBatis dynamic SQL tags Feb 26, 2024 pm 07:48 PM

    Interpretation of MyBatis dynamic SQL tags: Detailed explanation of Set tag usage MyBatis is an excellent persistence layer framework. It provides a wealth of dynamic SQL tags and can flexibly construct database operation statements. Among them, the Set tag is used to generate the SET clause in the UPDATE statement, which is very commonly used in update operations. This article will explain in detail the usage of the Set tag in MyBatis and demonstrate its functionality through specific code examples. What is Set tag Set tag is used in MyBati

    How to use Redis to implement distributed locks in SpringBoot How to use Redis to implement distributed locks in SpringBoot Jun 03, 2023 am 08:16 AM

    1. Redis implements distributed lock principle and why distributed locks are needed. Before talking about distributed locks, it is necessary to explain why distributed locks are needed. The opposite of distributed locks is stand-alone locks. When we write multi-threaded programs, we avoid data problems caused by operating a shared variable at the same time. We usually use a lock to mutually exclude the shared variables to ensure the correctness of the shared variables. Its scope of use is in the same process. If there are multiple processes that need to operate a shared resource at the same time, how can they be mutually exclusive? Today's business applications are usually microservice architecture, which also means that one application will deploy multiple processes. If multiple processes need to modify the same row of records in MySQL, in order to avoid dirty data caused by out-of-order operations, distribution needs to be introduced at this time. The style is locked. Want to achieve points

    How to solve the problem that springboot cannot access the file after reading it into a jar package How to solve the problem that springboot cannot access the file after reading it into a jar package Jun 03, 2023 pm 04:38 PM

    Springboot reads the file, but cannot access the latest development after packaging it into a jar package. There is a situation where springboot cannot read the file after packaging it into a jar package. The reason is that after packaging, the virtual path of the file is invalid and can only be accessed through the stream. Read. The file is under resources publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

    Comparison and difference analysis between SpringBoot and SpringMVC Comparison and difference analysis between SpringBoot and SpringMVC Dec 29, 2023 am 11:02 AM

    SpringBoot and SpringMVC are both commonly used frameworks in Java development, but there are some obvious differences between them. This article will explore the features and uses of these two frameworks and compare their differences. First, let's learn about SpringBoot. SpringBoot was developed by the Pivotal team to simplify the creation and deployment of applications based on the Spring framework. It provides a fast, lightweight way to build stand-alone, executable

    How to implement Springboot+Mybatis-plus without using SQL statements to add multiple tables How to implement Springboot+Mybatis-plus without using SQL statements to add multiple tables Jun 02, 2023 am 11:07 AM

    When Springboot+Mybatis-plus does not use SQL statements to perform multi-table adding operations, the problems I encountered are decomposed by simulating thinking in the test environment: Create a BrandDTO object with parameters to simulate passing parameters to the background. We all know that it is extremely difficult to perform multi-table operations in Mybatis-plus. If you do not use tools such as Mybatis-plus-join, you can only configure the corresponding Mapper.xml file and configure The smelly and long ResultMap, and then write the corresponding sql statement. Although this method seems cumbersome, it is highly flexible and allows us to

    How SpringBoot customizes Redis to implement cache serialization How SpringBoot customizes Redis to implement cache serialization Jun 03, 2023 am 11:32 AM

    1. Customize RedisTemplate1.1, RedisAPI default serialization mechanism. The API-based Redis cache implementation uses the RedisTemplate template for data caching operations. Here, open the RedisTemplate class and view the source code information of the class. publicclassRedisTemplateextendsRedisAccessorimplementsRedisOperations, BeanClassLoaderAware{//Declare key, Various serialization methods of value, the initial value is empty @NullableprivateRedisSe

    See all articles