From 4c127532479770725db7f8368b8d6deb2ec670db Mon Sep 17 00:00:00 2001 From: mxd <838425805@qq.com> Date: Fri, 14 Jan 2022 23:59:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4`assert`=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9E`ElasticSearch`=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- magic-api-spring-boot-starter/pom.xml | 5 + .../starter/MagicAPIAutoConfiguration.java | 4 +- .../MagicElasticSearchAutoConfiguration.java | 21 ++++ magic-api/pom.xml | 5 + .../magicapi/model/JsonCodeConstants.java | 2 +- .../magicapi/modules/AssertModule.java | 102 ------------------ .../magicapi/modules/ElasticSearchModule.java | 32 ++++++ .../ElasticSearchConnection.java | 58 ++++++++++ .../elasticsearch/ElasticSearchIndex.java | 77 +++++++++++++ .../elasticsearch/ElasticSearchRest.java | 97 +++++++++++++++++ .../ssssssss/magicapi/utils/JsonUtils.java | 9 ++ pom.xml | 8 +- 12 files changed, 313 insertions(+), 107 deletions(-) create mode 100644 magic-api-spring-boot-starter/src/main/java/org/ssssssss/magicapi/spring/boot/starter/MagicElasticSearchAutoConfiguration.java delete mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/AssertModule.java create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/ElasticSearchModule.java create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchConnection.java create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchIndex.java create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchRest.java diff --git a/magic-api-spring-boot-starter/pom.xml b/magic-api-spring-boot-starter/pom.xml index 52fdf4d1..1c0c41e5 100644 --- a/magic-api-spring-boot-starter/pom.xml +++ b/magic-api-spring-boot-starter/pom.xml @@ -28,6 +28,11 @@ spring-boot-starter-data-mongodb provided + + org.springframework.boot + spring-boot-starter-data-elasticsearch + provided + org.springframework.boot spring-boot-starter-web diff --git a/magic-api-spring-boot-starter/src/main/java/org/ssssssss/magicapi/spring/boot/starter/MagicAPIAutoConfiguration.java b/magic-api-spring-boot-starter/src/main/java/org/ssssssss/magicapi/spring/boot/starter/MagicAPIAutoConfiguration.java index 312446a3..5b9e2bad 100644 --- a/magic-api-spring-boot-starter/src/main/java/org/ssssssss/magicapi/spring/boot/starter/MagicAPIAutoConfiguration.java +++ b/magic-api-spring-boot-starter/src/main/java/org/ssssssss/magicapi/spring/boot/starter/MagicAPIAutoConfiguration.java @@ -87,7 +87,7 @@ import java.util.function.BiFunction; @Configuration @ConditionalOnClass({RequestMappingHandlerMapping.class}) @EnableConfigurationProperties(MagicAPIProperties.class) -@Import({MagicRedisAutoConfiguration.class, MagicMongoAutoConfiguration.class, MagicJsonAutoConfiguration.class, ApplicationUriPrinter.class}) +@Import({MagicRedisAutoConfiguration.class, MagicElasticSearchAutoConfiguration.class, MagicMongoAutoConfiguration.class, MagicJsonAutoConfiguration.class, ApplicationUriPrinter.class}) @EnableWebSocket public class MagicAPIAutoConfiguration implements WebMvcConfigurer, WebSocketConfigurer { @@ -500,8 +500,6 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer, WebSocketCon MagicResourceLoader.addModule("request", new RequestModule(multipartResolver)); logger.info("注册模块:{} -> {}", "response", ResponseModule.class); MagicResourceLoader.addModule("response", new ResponseModule(resultProvider)); - logger.info("注册模块:{} -> {}", "assert", AssertModule.class); - MagicResourceLoader.addModule("assert", new AssertModule()); magicModules.forEach(module -> { logger.info("注册模块:{} -> {}", module.getModuleName(), module.getClass()); MagicResourceLoader.addModule(module.getModuleName(), module); diff --git a/magic-api-spring-boot-starter/src/main/java/org/ssssssss/magicapi/spring/boot/starter/MagicElasticSearchAutoConfiguration.java b/magic-api-spring-boot-starter/src/main/java/org/ssssssss/magicapi/spring/boot/starter/MagicElasticSearchAutoConfiguration.java new file mode 100644 index 00000000..9fbe8f2b --- /dev/null +++ b/magic-api-spring-boot-starter/src/main/java/org/ssssssss/magicapi/spring/boot/starter/MagicElasticSearchAutoConfiguration.java @@ -0,0 +1,21 @@ +package org.ssssssss.magicapi.spring.boot.starter; + +import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.ssssssss.magicapi.modules.ElasticSearchModule; + +@Configuration +@ConditionalOnMissingBean(ElasticSearchModule.class) +@ConditionalOnClass(RestHighLevelClient.class) +public class MagicElasticSearchAutoConfiguration { + + @Bean + @ConditionalOnBean(RestHighLevelClient.class) + public ElasticSearchModule elasticSearchModule(RestHighLevelClient restHighLevelClient){ + return new ElasticSearchModule(restHighLevelClient.getLowLevelClient()); + } +} diff --git a/magic-api/pom.xml b/magic-api/pom.xml index 469c21a0..e5a7ff3c 100644 --- a/magic-api/pom.xml +++ b/magic-api/pom.xml @@ -41,6 +41,11 @@ spring-boot-starter-web provided + + org.elasticsearch.client + elasticsearch-rest-high-level-client + provided + org.springframework spring-jdbc diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/model/JsonCodeConstants.java b/magic-api/src/main/java/org/ssssssss/magicapi/model/JsonCodeConstants.java index 5029cd66..5920815b 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/model/JsonCodeConstants.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/model/JsonCodeConstants.java @@ -41,7 +41,7 @@ public interface JsonCodeConstants { JsonCode FILE_PATH_NOT_EXISTS = new JsonCode(1015, "配置的文件路径不存在,请检查"); - JsonCode REQUEST_PATH_CONFLICT = new JsonCode(1016, "接口[{}({})]与应用冲突,无法注册"); + JsonCode REQUEST_PATH_CONFLICT = new JsonCode(1016, "接口[%s(%s)]与应用冲突,无法注册"); JsonCode SCRIPT_REQUIRED = new JsonCode(1017, "脚本内容不能为空"); diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/AssertModule.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/AssertModule.java deleted file mode 100644 index 725cb3c5..00000000 --- a/magic-api/src/main/java/org/ssssssss/magicapi/modules/AssertModule.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.ssssssss.magicapi.modules; - -import org.apache.commons.lang3.StringUtils; -import org.ssssssss.magicapi.config.MagicModule; -import org.ssssssss.script.annotation.Comment; -import org.ssssssss.script.exception.MagicScriptAssertException; - -import java.util.regex.Pattern; - -/** - * 断言模块 - * - * @author mxd - */ -public class AssertModule implements MagicModule { - - /** - * 判断值不能为null - * - * @param value 值 - * @param code 状态码 - * @param message 状态说明 - */ - @Comment("判断值不能为空") - public void notNull(@Comment(name = "value", value = "值") Object value, - @Comment(name = "code", value = "判断失败时的code") int code, - @Comment(name = "message", value = "判断失败时的说明") String message) { - if (value == null) { - throw new MagicScriptAssertException(code, message); - } - } - - /** - * 判断值不能为empty - * - * @param value 值 - * @param code 状态码 - * @param message 状态说明 - */ - @Comment("判断值不能为Empty") - public void notEmpty(@Comment(name = "value", value = "值") String value, - @Comment(name = "code", value = "判断失败时的code") int code, - @Comment(name = "message", value = "判断失败时的说明") String message) { - if (StringUtils.isEmpty(value)) { - throw new MagicScriptAssertException(code, message); - } - } - - /** - * 判断值不能为blank - * - * @param value 值 - * @param code 状态码 - * @param message 状态说明 - */ - @Comment("判断值不能为Blank") - public void notBlank(@Comment(name = "value", value = "值") String value, - @Comment(name = "code", value = "判断失败时的code") int code, - @Comment(name = "message", value = "判断失败时的说明") String message) { - if (StringUtils.isBlank(value)) { - throw new MagicScriptAssertException(code, message); - } - } - - /** - * 正则验证值 - * - * @param value 值 - * @param code 状态码 - * @param message 状态说明 - */ - @Comment("正则判断") - public void regx(@Comment(name = "value", value = "值") String value, String pattern, - @Comment(name = "code", value = "判断失败时的code") int code, - @Comment(name = "message", value = "判断失败时的说明") String message) { - if (value == null || !Pattern.compile(pattern).matcher(value).matches()) { - throw new MagicScriptAssertException(code, message); - } - } - - /** - * 判断值值是否为true - * - * @param value 值 - * @param code 状态码 - * @param message 状态说明 - */ - @Comment("判断值是否为true") - public void isTrue(@Comment(name = "value", value = "值") boolean value, - @Comment(name = "code", value = "判断失败时的code") int code, - @Comment(name = "message", value = "判断失败时的说明") String message) { - if (!value) { - throw new MagicScriptAssertException(code, message); - } - } - - - @Override - public String getModuleName() { - return "assert"; - } -} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/ElasticSearchModule.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/ElasticSearchModule.java new file mode 100644 index 00000000..7cef939a --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/ElasticSearchModule.java @@ -0,0 +1,32 @@ +package org.ssssssss.magicapi.modules; + +import org.elasticsearch.client.RestClient; +import org.ssssssss.magicapi.config.MagicModule; +import org.ssssssss.magicapi.modules.elasticsearch.ElasticSearchConnection; +import org.ssssssss.magicapi.modules.elasticsearch.ElasticSearchIndex; +import org.ssssssss.script.annotation.Comment; + +public class ElasticSearchModule implements MagicModule { + + private static final String DOC = "_doc"; + + private final RestClient restClient; + + public ElasticSearchModule(RestClient restClient) { + this.restClient = restClient; + } + + @Comment(value = "ElasticSearch REST Api") + public ElasticSearchConnection rest(String url){ + return new ElasticSearchConnection(this.restClient, url); + } + + public ElasticSearchIndex index(String indexName){ + return new ElasticSearchIndex(this.restClient, indexName, DOC); + } + + @Override + public String getModuleName() { + return "elasticsearch"; + } +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchConnection.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchConnection.java new file mode 100644 index 00000000..c824ad0a --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchConnection.java @@ -0,0 +1,58 @@ +package org.ssssssss.magicapi.modules.elasticsearch; + +import org.apache.http.HttpEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.util.EntityUtils; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.ml.PutJobResponse; +import org.ssssssss.magicapi.utils.JsonUtils; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Objects; + +public class ElasticSearchConnection extends ElasticSearchRest { + + public ElasticSearchConnection(RestClient restClient, String endpoint) { + super(restClient); + super.endpoint(endpoint); + } + + public ElasticSearchConnection parameter(String key, String value) { + if (value != null) { + parameters.put(key, value); + } + return this; + } + + public ElasticSearchConnection parameters(Map params) { + if (params != null) { + parameters.putAll(params); + } + return this; + } + + public Object put(Object data) throws IOException { + return processResponse(json(data).doPut()); + } + + public Object delete() throws IOException { + return processResponse(doDelete()); + } + + public Object delete(Object data) throws IOException { + return processResponse(json(data).doDelete()); + } + + public Object post(Object data) throws IOException { + return processResponse(json(data).doPost()); + } + + public Object get() throws IOException { + return processResponse(doGet()); + } + +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchIndex.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchIndex.java new file mode 100644 index 00000000..4eb749a6 --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchIndex.java @@ -0,0 +1,77 @@ +package org.ssssssss.magicapi.modules.elasticsearch; + +import org.elasticsearch.client.RestClient; +import org.ssssssss.magicapi.utils.JsonUtils; +import org.ssssssss.script.annotation.Comment; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class ElasticSearchIndex { + + private final RestClient restClient; + + private final String name; + + private final String type; + + + public ElasticSearchIndex(RestClient restClient, String name, String type) { + this.restClient = restClient; + this.name = name; + this.type = type; + } + + @Comment("根据`_id`保存,当存在时更新,不存在时插入") + public Object save(@Comment(value = "_id", name = "_id")String _id, @Comment(value = "保存对象", name = "data")Object data) throws IOException { + return connect("/%s/%s/%s", this.name, this.type, _id).post(data); + } + + @Comment("不指定`_id`插入") + public Object insert(@Comment(value = "插入对象", name = "data")Object data) throws IOException { + return connect("/%s/%s", this.name, this.type).post(data); + } + + @Comment("指定`_id`插入,当`_id`存在时不会更新") + public Object insert(@Comment(value = "_id", name = "_id")String _id, @Comment(value = "插入对象", name = "data")Object data) throws IOException { + return connect("/%s/%s/%s/_create", this.name, this.type, _id).post(data); + } + + @Comment("根据`id`删除") + public Object delete(@Comment(value = "id", name = "id")String id) throws IOException { + return connect("/%s/%s/%s", this.name, this.type, id).delete(); + } + + @Comment("批量保存,当包含`id`时,则使用该列值匹配保存") + public Object bulkSave(@Comment(value = "保存内容", name = "list") List> list) throws IOException { + StringBuilder builder = new StringBuilder(); + list.forEach(item -> { + Object id = item.get("id"); + if(id != null){ + builder.append(String.format("{ \"index\":{ \"_id\": \"%s\" } }\r\n", id)); + } else { + builder.append("{ \"index\":{} }\r\n"); + } + builder.append(JsonUtils.toJsonStringWithoutPretty(item)); + builder.append("\r\n"); + }); + return connect("/%s/%s/_bulk", this.name, this.type).post(builder.toString()); + } + + @Comment("根据`_id`修改") + public Object update(@Comment(value = "_id", name = "_id")String _id, @Comment(value = "修改项", name = "data")Object data) throws IOException { + return connect("/%s/%s/%s", this.name, this.type, _id).post(Collections.singletonMap("doc", data)); + } + + @Comment("搜索") + public Object search(@Comment(value = "搜索`DSL`语句", name = "dsl")Map dsl) throws IOException { + return connect("/%s/_search", this.name).post(dsl); + } + + private ElasticSearchConnection connect(String format, Object... args) { + return new ElasticSearchConnection(this.restClient, String.format(format, args)); + } +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchRest.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchRest.java new file mode 100644 index 00000000..7bc49571 --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/elasticsearch/ElasticSearchRest.java @@ -0,0 +1,97 @@ +package org.ssssssss.magicapi.modules.elasticsearch; + +import org.apache.http.HttpEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.nio.entity.NStringEntity; +import org.apache.http.util.EntityUtils; +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.xcontent.XContentParserUtils; +import org.ssssssss.magicapi.utils.JsonUtils; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class ElasticSearchRest { + + private final RestClient restClient; + + private String method; + + private String endpoint = "/"; + + private HttpEntity entity; + + protected final Map parameters = new HashMap<>(); + + public ElasticSearchRest(RestClient restClient) { + this.restClient = restClient; + } + + ElasticSearchRest endpoint(String endpoint){ + this.endpoint = endpoint; + return this; + } + + Response doGet() throws IOException { + this.method = "GET"; + return execute(); + } + + Response doPost() throws IOException { + this.method = "POST"; + return execute(); + } + + Response doDelete() throws IOException { + this.method = "DELETE"; + return execute(); + } + + Response doPut() throws IOException { + this.method = "PUT"; + return execute(); + } + + ElasticSearchRest json(Object data){ + if(data == null){ + return this; + } + String json = null; + if(data instanceof CharSequence){ + json = data.toString(); + } else { + json = JsonUtils.toJsonString(data); + } + if(json != null){ + this.entity = new NStringEntity(json, ContentType.APPLICATION_JSON); + } + return this; + } + + private Response execute() throws IOException { + Request request = new Request(method, this.endpoint); + request.addParameters(parameters); + request.setEntity(entity); + return this.restClient.performRequest(request); + } + + Object processResponse(Response response) throws IOException { + int code = response.getStatusLine().getStatusCode(); + if (code >= 200 && code < 300) { // 2xx + HttpEntity entity = response.getEntity(); + String resp = EntityUtils.toString(entity, StandardCharsets.UTF_8); + ContentType contentType = ContentType.get(entity); + if (Objects.equals(ContentType.APPLICATION_JSON.getMimeType(), contentType.getMimeType())) { + return JsonUtils.readValue(resp, Object.class); + } + } + return response; + } +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/utils/JsonUtils.java b/magic-api/src/main/java/org/ssssssss/magicapi/utils/JsonUtils.java index 65a59a77..652934ca 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/utils/JsonUtils.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/utils/JsonUtils.java @@ -44,6 +44,15 @@ public class JsonUtils { } } + public static String toJsonStringWithoutPretty(Object target) { + try { + return MAPPER.writeValueAsString(target); + } catch (JsonProcessingException e) { + logger.error("json序列化失败", e); + return null; + } + } + public static String toJsonStringWithoutLog(Object target) { try { return MAPPER.writeValueAsString(target); diff --git a/pom.xml b/pom.xml index 221b7c19..28f0c139 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,8 @@ 2.4.5 - 1.6.3 + 1.6.4 + 7.15.0 1.21 2.7 1.6 @@ -102,6 +103,11 @@ springfox-swagger2 ${swagger.version} + + org.elasticsearch.client + elasticsearch-rest-high-level-client + ${elasticsearch.version} +