set 명령 구문
SET 키 id [FIELD 이름 값 ...] [EX 초] [NX|XX] (OBJECT geojson)|(POINT lat lon z)|(BOUNDS minlat minlon maxlat maxlon) |(HASH geohash)|(STRING 값)
set
명령은 redis의 hash
명령 사용과 동일하며 키이기도 합니다.
및 id
이지만 차이점은 Tile38의 set
명령이 FIELD
필드 사용자 정의와 같은 더 많은 다른 속성도 전달할 수 있다는 것입니다. EX
유효 기간 등을 설정할 수도 있습니다. 그런 다음 개발자가 Tile38을 더 잘 사용할 수 있도록 이 구문에 유용한 java api
를 설계해야 합니다. set
命令就相当于redis中的hash
命令的使用,也是一个key
和id
的组合,但是不同的是,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; } }
因为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); } } }
我们上面通过建造者的设计模式,把所有的参数都转换成了SetOpts这个类当中,开发人员就可以通过SetOpts对象的构建来灵活地控制命令中的参数了。
3.我们需要把第三部分当中的不同数据对象转换成不同的类型:
POINT数据类型
Point关键的字段就是经纬度,除此之外,还有一个额外的字段z
SET
명령의 계시 키워드입니다. 이 키워드를 별도의 부분으로 ;2. 두 번째 부분은 key id [FIELD 이름 값 ...] [EX 초] [NX|XX]
이며 이를 매개변수로 사용합니다. 3. 세 번째 부분 최종 대상 데이터 객체입니다:
(OBJECT geojson)|(POINT lat lon z)|(BOUNDS minlat minlon maxlat maxlon)|(HASH geohash)|(STRING value)
코드 디자인 1. 첫 번째 부분에 있는 명령 키워드는 열거를 통해 관리됩니다.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; } }Redis 클라이언트 도구는 모든 명령을 보내기 전에 인코딩해야 하기 때문에 모든 명령은
ProtocolKeyword
인터페이스를 구현해야 합니다. 명령의 시작 키워드가 두 단어 이상인 경우 밑줄을 사용하여 연결합니다. 바이트로 변환할 때 밑줄을 대체하기 위해 공백을 사용할 수 있습니다. 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;
}
}
빌더 디자인 패턴을 사용하여 모든 매개변수를 SetOpts 클래스로 변환했습니다. 개발자는 명령에서 매개변수를 유연하게 제어할 수 있습니다. SetOpts 객체의 구성을 통해. 3. 세 번째 부분의 다양한 데이터 개체를 다양한 유형으로 변환해야 합니다. 🎜🎜POINT 데이터 유형 🎜🎜Point의 핵심 필드는 위도와 경도입니다. 또한 추가 필드 z가 있습니다. 추가 비즈니스 매개변수를 저장하는 데 사용되는
는 비워둘 수 있습니다. 🎜@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; } }🎜BOUNDS 데이터 유형🎜🎜BOUNDS는 직사각형이며 주요 필드는 왼쪽 하단 모서리와 오른쪽 상단 모서리입니다. 좌표 1과 좌표 2를 사용하여 🎜
Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon🎜HASH 및 STRING 데이터 유형을 나타냅니다. 🎜 🎜HASH와 STRING은 실제로 별도의 문자열이지만 개발자가 사용할 수 있도록 캡슐화합니다. 🎜
@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(); } } }🎜OBJECT 데이터 유형🎜🎜OBJECT는 실제로 GeoJSON 데이터 유형이며 총 6개가 있습니다. 자세한 내용을 알고 싶은 사람은 여기 geojson.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 } }🎜를 참조하세요. 개발자가 이 6가지 유형을 더 잘 사용할 수 있도록 빌더 패턴을 사용하여 GeoJSON 데이터 유형을 디자인합니다. 이 경우에는 이 클래스에 객체를 생성하는 6가지 방법이 있으며 각 빌더는 해당 객체를 빌드하는 역할만 담당합니다. 🎜🎜다음은 6개 빌더의 코드입니다. 각 객체는 가장 기본적인 BaseGeoJson을 기반으로 구성됩니다. 공개 필드 유형과 추가 메타 필드는 BaseGeoJson에서 추출됩니다. 각 유형의 차이는 좌표 지점 수에 있습니다. 레벨이 다르기 때문에 각 유형의 특성에 따라 코드 디자인은 다음과 같습니다. 🎜
public abstract class Element implements Serializable { public abstract List<String> commandArgs(); }🎜마지막으로 기본 클래스 추가 요소: 🎜
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); }🎜사용 방법🎜🎜모든 데이터 유형을 특정 코드 디자인으로 변환합니다. , 아래를 살펴보겠습니다. 사용 방법 보기: 🎜rrreee
위 내용은 Springboot 통합 타일 클라이언트의 Set 명령을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

이 기사에서는 Java 프로젝트 관리, 구축 자동화 및 종속성 해상도에 Maven 및 Gradle을 사용하여 접근 방식과 최적화 전략을 비교합니다.

이 기사에서는 Maven 및 Gradle과 같은 도구를 사용하여 적절한 버전 및 종속성 관리로 사용자 정의 Java 라이브러리 (JAR Files)를 작성하고 사용하는 것에 대해 설명합니다.

이 기사는 카페인 및 구아바 캐시를 사용하여 자바에서 다단계 캐싱을 구현하여 응용 프로그램 성능을 향상시키는 것에 대해 설명합니다. 구성 및 퇴거 정책 관리 Best Pra와 함께 설정, 통합 및 성능 이점을 다룹니다.

이 기사는 캐싱 및 게으른 하중과 같은 고급 기능을 사용하여 객체 관계 매핑에 JPA를 사용하는 것에 대해 설명합니다. 잠재적 인 함정을 강조하면서 성능을 최적화하기위한 설정, 엔티티 매핑 및 모범 사례를 다룹니다. [159 문자]

Java의 클래스 로딩에는 부트 스트랩, 확장 및 응용 프로그램 클래스 로더가있는 계층 적 시스템을 사용하여 클래스로드, 링크 및 초기화 클래스가 포함됩니다. 학부모 위임 모델은 핵심 클래스가 먼저로드되어 사용자 정의 클래스 LOA에 영향을 미치도록합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

WebStorm Mac 버전
유용한 JavaScript 개발 도구

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

드림위버 CS6
시각적 웹 개발 도구
