diff --git a/LICENSE b/LICENSE index e69de29b..261eeb9e 100644 --- a/LICENSE +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README-ZH.md b/README-ZH.md new file mode 100644 index 00000000..27b75bc4 --- /dev/null +++ b/README-ZH.md @@ -0,0 +1,113 @@ +

+ + East-Es-Logo + +

+ +

+ 为简化开发工作、提高生产效率而生 +

+ +

+ + maven + + + + code style + +

+ +# 简介 | Intro + +Easy-Es是一款简化ElasticSearch搜索引擎操作的开源框架,简化`CRUD`操作,可以更好的帮助开发者减轻开发负担 + +底层采用Es官方提供的RestHighLevelClient,保证其原生性能及拓展性. + +技术讨论 QQ 群 :247637156 + +# 优点 | Advantages + +- **屏蔽语言差异:** 开发者只需要会MySQL语法即可使用Es + +- **低码:** 与直接使用RestHighLevelClient相比,相同的查询平均可以节3-5倍左右的代码量 +- **零魔法值:** 字段名称直接从实体中获取,无需输入字段名称字符串这种魔法值 +- **零额外学习成本:** 开发者只要会国内最受欢迎的Mybatis-Plus语法,即可无缝迁移至Easy-Es +- **降低开发者门槛:** 即便是只了解ES基础的初学者也可以轻松驾驭ES完成绝大多数需求的开发 +- **...** + +## 对比 | Compare +> 需求:查询出文档标题为 "中国功夫"且作者为"老汉"的所有文档 +```java +// 使用Easy-Es仅需3行代码即可完成查询 +LambdaEsQueryWrapper wrapper = new LambdaEsQueryWrapper<>(); +wrapper.eq(Document::getTitle, "中国功夫").eq(Document::getCreator, "老汉"); +List documents = documentMapper.selectList(wrapper); +``` + +```java +// 传统方式, 直接用RestHighLevelClient进行查询 需要11行代码,还不包含解析JSON代码 +String indexName = "document"; +SearchRequest searchRequest = new SearchRequest(indexName); +BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); +TermQueryBuilder titleTerm = QueryBuilders.termQuery("title", "中国功夫"); +TermsQueryBuilder creatorTerm = QueryBuilders.termsQuery("creator", "老汉"); +boolQueryBuilder.must(titleTerm); +boolQueryBuilder.must(creatorTerm); +SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); +searchSourceBuilder.query(boolQueryBuilder); +searchRequest.source(searchSourceBuilder); +try { + SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); + // 然后从searchResponse中通过各种方式解析出DocumentList 省略这些代码... + } catch (IOException e) { + e.printStackTrace(); + } +``` +> * 以上只是简单查询演示,实际使用场景越复杂,效果就越好,平均可节省3-5倍代码量 +> * 上述功能仅供演示,仅为Easy-Es支持功能的冰山一角 + +## 相关链接 | Links + +- [文档](https://www.yuque.com/laohan-14b9d/foyrfa/naw1ie) +- [功能示例](https://github.com/xpc1024/easy-es/tree/main/easy-es-sample) +- [Springboot集成Demo](https://www.yuque.com/laohan-14b9d/foyrfa/pbo22k) + +# Latest Version: [![Maven Central](https://img.shields.io/github/v/release/xpc1024/easy-es?include_prereleases&logo=xpc&style=plastic)](https://search.maven.org/search?q=g:io.github.xpc1024%20a:easy-*) + +**Maven:** +``` xml + + com.github.xpc1024 + easy-es-boot-starter + Latest Version + +``` +**Gradle:** +```groovy +compile group: 'com.github.xpc1024', name: 'easy-es-boot-starter', version: 'Latest Version' +``` + +# 其他开源项目 | Other Project + +- [健身计划一键生成系统](https://github.com/xpc1024/plan-all) + +# 期望 | Futures + +> 欢迎提出更好的意见,帮助完善 Easy-Es + +# 版权 | License + +[Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) + +# 捐赠 | Donate + +[捐赠记录,感谢你们的支持!](https://www.yuque.com/laohan-14b9d/foyrfa/ipxxr2) + +[捐赠 Easy-Es](https://www.yuque.com/laohan-14b9d/foyrfa/wn1iha) + +# 关注我 | About Me + +[CSDN博客](https://blog.csdn.net/lovexiaotaozi?spm=3001.5343) + +QQ | 微信:252645816 diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 38b53cc7..00000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# easy-es - -#### Description -更好用的elastic search 框架,底层采用RestHighLevelClient,语法采用Mybatis-plus一致的语法,只需要会MySQL语法即可完成对es的相关操作 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md index 2ac83ec2..05a5ff80 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@

- 为简化开发工作、提高生产效率而生 + Born To Simplify Development

@@ -18,40 +18,47 @@

-# 简介 | Intro +## What is Easy-Es? -Easy-Es是一款简化ElasticSearch搜索引擎操作的开源框架,简化`CRUD`操作,可以更好的帮助开发者减轻开发负担 +Easy-Es is a powerfully enhanced toolkit of RestHighLevelClient for simplify development. This toolkit provides some efficient, useful, out-of-the-box features for ElasticSearch. By using Easy-Es, you can use MySQL syntax to complete Es queries. Use it can effectively save your development time. -底层采用Es官方提供的RestHighLevelClient,保证其原生性能及拓展性 -技术讨论 QQ 群 : 待定 +## Links +- [中文版](https://github.com/xpc1024/easy-es/blob/main/README-ZH.md) +- [Documentation](https://www.yuque.com/laohan-14b9d/foyrfa/naw1ie) +- [Samples](https://github.com/xpc1024/easy-es/tree/main/easy-es-sample) +- [Demo in Springboot](https://github.com/xpc1024/easy-es-springboot-demo-en) -# 优点 | Advantages +## Features + +- Auto configuration on startup +- Out-of-the-box interfaces for operate es +- Powerful and flexible where condition wrapper +- Lambda-style API +- Automatic paging operation +- Support high-level syntax such as highlighting and weighting +- ... + +## Compare + +> Demand: Query all documents with title equals "Hi" and author equals "Guy" -- **屏蔽语言差异:** 开发者只需要会MySQL语法即可使用Es -- **低码:** 与直接使用RestHighLevelClient相比,相同的查询平均可以节3-5倍左右的代码量 -- **零魔法值:** 字段名称直接从实体中获取,无需输入字段名称字符串这种魔法值 -- **零额外学习成本:** 开发者只要会国内最受欢迎的Mybatis-Plus语法,即可无缝迁移至Easy-Es -- **降低开发者门槛:** 即便是只了解ES基础的初学者也可以轻松驾驭ES完成绝大多数需求的开发 -- **...** -## 对比 | Compare -> 需求:查询出文档标题为 "中国功夫"且作者为"老汉"的所有文档 ```java -// 使用Easy-Es仅需3行代码即可完成查询 +// Use Easy-Es to complete the query with only 3 lines of code LambdaEsQueryWrapper wrapper = new LambdaEsQueryWrapper<>(); -wrapper.eq(Document::getTitle, "中国功夫").eq(Document::getCreator, "老汉"); +wrapper.eq(Document::getTitle, "Hi").eq(Document::getCreator, "Guy"); List documents = documentMapper.selectList(wrapper); ``` ```java -// 传统方式, 直接用RestHighLevelClient进行查询 需要11行代码,还不包含解析JSON代码 +// Query directly with RestHighLevelClient requires 11 lines of code, not including parsing JSON code String indexName = "document"; SearchRequest searchRequest = new SearchRequest(indexName); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); -TermQueryBuilder titleTerm = QueryBuilders.termQuery("title", "中国功夫"); -TermsQueryBuilder creatorTerm = QueryBuilders.termsQuery("creator", "老汉"); +TermQueryBuilder titleTerm = QueryBuilders.termQuery("title", "Hi"); +TermsQueryBuilder creatorTerm = QueryBuilders.termsQuery("creator", "Guy"); boolQueryBuilder.must(titleTerm); boolQueryBuilder.must(creatorTerm); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); @@ -59,48 +66,91 @@ searchSourceBuilder.query(boolQueryBuilder); searchRequest.source(searchSourceBuilder); try { SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); - // 然后从searchResponse中通过各种方式解析出DocumentList 省略这些代码... + // Then parse the DocumentList from searchResponse in various ways, omitting these codes... } catch (IOException e) { e.printStackTrace(); } ``` ->以上只是简单查询演示,实际查询场景越复杂,效果就越好,平均可节省3-5倍代码量 -## 相关链接 | Links -- [文档](https://www.yuque.com/laohan-14b9d/foyrfa/naw1ie) -- [功能示例](samples) -- [展示](ee-use) +> The above is just a simple query demonstration. The more complex the actual query scene, the better the effect, which can save 3-5 times the amount of code on average. +## Getting started -# Latest Version: [![Maven Central](https://img.shields.io/github/v/release/xpc1024/easy-es?include_prereleases&logo=xpc&style=plastic)](https://search.maven.org/search?q=g:io.github.xpc1024%20a:easy-*) +- Add Easy-Es dependency + - Latest Version: [![Maven Central](https://img.shields.io/github/v/release/xpc1024/easy-es?include_prereleases&logo=xpc&style=plastic)](https://search.maven.org/search?q=g:io.github.xpc1024%20a:easy-*) + - Maven: + ```xml + + com.github.xpc1024 + easy-es-boot-starter + Latest Version + + ``` + - Gradle + ```groovy + compile group: 'com.github.xpc1024', name: 'easy-es-boot-starter', version: 'Latest Version' + ``` +- Add mapper file extends BaseEsMapper interface -``` xml - - com.github.xpc1024 - easy-es - Latest Version - -``` + ```java + public interface DocumentMapper extends BaseMapper { + } + ``` -# 其他开源项目 | Other Project +- Use it + ``` java + LambdaEsQueryWrapper wrapper = new LambdaEsQueryWrapper<>(); + wrapper.eq(Document::getTitle,"Hello World") + .eq(Document::getCreator,"Guy"); + List documentList = documentMapper.selectList(); + + ``` + Easy-Es will execute the following Query: + ```json + {"query":{"bool":{"must":[{"term":{"title":{"value":"Hello World","boost":1.0}}},{"term":{"creator":{"value":"Guy","boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}}} + ``` + + The syntax of this query in MySQL is: + ```sql + SELECT * FROM document WHERE title = 'Hello World' AND creator = 'Guy' + ``` + +> This showcase is just a small part of Easy-Es features. If you want to learn more, please refer to the [documentation](https://www.yuque.com/laohan-14b9d/foyrfa/naw1ie). -- [健身计划一键生成系统](https://github.com/xpc1024/plan-all) +## Syntax comparison with MySQL +| MySQL | Easy-Es | +| ---- | ---- | +| and | and | +| or | or | +| = | eq | +| != | ne| +| > | gt | +| >= | ge | +| < | lt | +| <= | le | +| like '%field%' | like | +| not like '%field%' |notLike| +| like '%field' | likeLeft| +| like 'field%' | likeRight | +| between | between | +| notBetween | notBetween | +| is null | isNull | +| is notNull | isNotNull | +| in | in | +| not in | notIn | +| group by | groupBy | +| order by | orderBy | +|min |min | +|max |max | +|avg |avg | +|sum |sum | +|sum |sum | +| - | orderByAsc | +| - | orderByDesc | +| - | match | +|- |highLight | +| ... | ... | -# 期望 | Futures -> 欢迎提出更好的意见,帮助完善 Easy-Es +## License -# 版权 | License - -[Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) - -# 捐赠 | Donate - -[捐赠记录,感谢你们的支持!](https://www.yuque.com/laohan-14b9d/foyrfa/ipxxr2) - -[捐赠 Easy-Es](https://www.yuque.com/laohan-14b9d/foyrfa/wn1iha) - -# 关注我 | About Me - -[CSDN博客](https://blog.csdn.net/lovexiaotaozi?spm=3001.5343) - -QQ | 微信:252645816 +Easy-Es is under the Apache 2.0 license. See the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) file for details. diff --git a/easy-es-boot-starter/pom.xml b/easy-es-boot-starter/pom.xml new file mode 100644 index 00000000..d80dd9e5 --- /dev/null +++ b/easy-es-boot-starter/pom.xml @@ -0,0 +1,36 @@ + + + + easy-es-parent + io.github.xpc1024 + 0.9.3 + ../easy-es-parent + + 4.0.0 + + easy-es-boot-starter + + + 8 + 8 + + + + + io.github.xpc1024 + easy-es-core + 0.9.3 + + + org.springframework.boot + spring-boot-autoconfigure + + + commons-codec + commons-codec + + + + \ No newline at end of file diff --git a/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/annotation/EsMapperScan.java b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/annotation/EsMapperScan.java new file mode 100644 index 00000000..1cc222c9 --- /dev/null +++ b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/annotation/EsMapperScan.java @@ -0,0 +1,20 @@ +package com.xpc.easyes.autoconfig.annotation; + + +import com.xpc.easyes.autoconfig.register.MapperScannerRegister; +import org.springframework.context.annotation.Import; + +import java.lang.annotation.*; + +/** + * 全局Mapper扫描注解 + *

+ * Copyright © 2021 xpc1024 All Rights Reserved + **/ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Import(MapperScannerRegister.class) +public @interface EsMapperScan { + String value(); +} diff --git a/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/config/EsAutoConfiguration.java b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/config/EsAutoConfiguration.java new file mode 100644 index 00000000..60222e20 --- /dev/null +++ b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/config/EsAutoConfiguration.java @@ -0,0 +1,106 @@ +package com.xpc.easyes.autoconfig.config; + +import com.xpc.easyes.autoconfig.constants.PropertyKeyConstants; +import com.xpc.easyes.core.cache.GlobalConfigCache; +import com.xpc.easyes.core.config.GlobalConfig; +import com.xpc.easyes.core.enums.FieldStrategy; +import com.xpc.easyes.core.enums.IdType; +import com.xpc.easyes.core.toolkit.ExceptionUtils; +import com.xpc.easyes.core.toolkit.StringUtils; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.EnvironmentAware; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import java.util.*; + +import static com.xpc.easyes.core.constants.BaseEsConstants.COLON; +import static com.xpc.easyes.core.constants.BaseEsConstants.DEFAULT_SCHEMA; + +/** + * es自动配置 + *

+ * Copyright © 2021 xpc1024 All Rights Reserved + **/ +@Configuration +@EnableConfigurationProperties(EsConfigProperties.class) +@ConditionalOnClass(RestHighLevelClient.class) +@ConditionalOnProperty(prefix = "easy-es", name = {"enable"}, havingValue = "true", matchIfMissing = true) +public class EsAutoConfiguration implements InitializingBean, EnvironmentAware, PropertyKeyConstants { + @Autowired + private EsConfigProperties esConfigProperties; + private Environment environment; + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Bean + @ConditionalOnMissingBean + public RestHighLevelClient restHighLevelClient() { + // 处理地址 + String address = environment.getProperty(ADDRESS); + if (StringUtils.isEmpty(address)) { + throw ExceptionUtils.eee("please config the es address"); + } + if (!address.contains(COLON)) { + throw ExceptionUtils.eee("the address must contains port and separate by ':'"); + } + String schema = StringUtils.isEmpty(esConfigProperties.getSchema()) + ? DEFAULT_SCHEMA : esConfigProperties.getSchema(); + List hostList = new ArrayList<>(); + Arrays.stream(esConfigProperties.getAddress().split(",")) + .forEach(item -> hostList.add(new HttpHost(item.split(":")[0], + Integer.parseInt(item.split(":")[1]), schema))); + + // 转换成 HttpHost 数组 + HttpHost[] httpHost = hostList.toArray(new HttpHost[]{}); + // 构建连接对象 + RestClientBuilder builder = RestClient.builder(httpHost); + + // 设置账号密码之类的 + String username = environment.getProperty(USERNAME); + String password = environment.getProperty(PASSWORD); + if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) { + final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + // 设置账号密码 + credentialsProvider.setCredentials(AuthScope.ANY, + new UsernamePasswordCredentials(esConfigProperties.getUsername(), esConfigProperties.getPassword())); + builder.setHttpClientConfigCallback(httpClientBuilder -> { + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + return httpClientBuilder; + }); + } + //TODO 其它设置,比如超时时间 异步之类的 后续优化 + + return new RestHighLevelClient(builder); + } + + @Override + public void afterPropertiesSet() throws Exception { + GlobalConfig globalConfig = new GlobalConfig(); + GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig(); + Optional.ofNullable(environment.getProperty(TABLE_PREFIX)).ifPresent(dbConfig::setTablePrefix); + Optional.ofNullable(environment.getProperty(ID_TYPE)) + .ifPresent(i -> dbConfig.setIdType(Enum.valueOf(IdType.class, i.toUpperCase(Locale.ROOT)))); + Optional.ofNullable(environment.getProperty(FIELD_STRATEGY)) + .ifPresent(f -> dbConfig.setFieldStrategy(Enum.valueOf(FieldStrategy.class, f.toUpperCase(Locale.ROOT)))); + globalConfig.setDbConfig(dbConfig); + GlobalConfigCache.setGlobalConfig(globalConfig); + } +} diff --git a/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/config/EsConfigProperties.java b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/config/EsConfigProperties.java new file mode 100644 index 00000000..38ceeb5c --- /dev/null +++ b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/config/EsConfigProperties.java @@ -0,0 +1,30 @@ +package com.xpc.easyes.autoconfig.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * 基础配置模型 + *

+ * Copyright © 2021 xpc1024 All Rights Reserved + **/ +@Data +@ConfigurationProperties(prefix = "easy-es") +public class EsConfigProperties { + /** + * es 连接地址 + */ + private String address; + /** + * 模式 + */ + private String schema; + /** + * 用户名 + */ + private String username; + /** + * 密码 可缺省 + */ + private String password; +} diff --git a/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/constants/PropertyKeyConstants.java b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/constants/PropertyKeyConstants.java new file mode 100644 index 00000000..0f58c7fb --- /dev/null +++ b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/constants/PropertyKeyConstants.java @@ -0,0 +1,41 @@ +package com.xpc.easyes.autoconfig.constants; + +/** + * 属性key常量 + *

+ * Copyright © 2021 xpc1024 All Rights Reserved + **/ +public interface PropertyKeyConstants { + /** + * es 地址 + */ + String ADDRESS = "easy-es.address"; + /** + * 属性 + */ + String SCHEMA = "easy-es.schema"; + /** + * es用户名 + */ + String USERNAME = "easy-es.username"; + /** + * es密码 + */ + String PASSWORD = "easy-es.password"; + /** + * 框架banner是否展示 + */ + String BANNER = "easy-es.global-config.db-config.banner"; + /** + * es索引前缀 + */ + String TABLE_PREFIX = "easy-es.global-config.db-config.table-prefix"; + /** + * es id类型 + */ + String ID_TYPE = "easy-es.global-config.db-config.id-type"; + /** + * es 字段策略 + */ + String FIELD_STRATEGY = "easy-es.global-config.db-config.field-strategy"; +} diff --git a/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/register/ClassPathMapperScanner.java b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/register/ClassPathMapperScanner.java new file mode 100644 index 00000000..410505a8 --- /dev/null +++ b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/register/ClassPathMapperScanner.java @@ -0,0 +1,90 @@ +package com.xpc.easyes.autoconfig.register; + +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; + +import java.util.Arrays; +import java.util.Set; + +/** + * 扫描指定路径下的所有接口 + *

+ * Copyright © 2021 xpc1024 All Rights Reserved + **/ +public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner { + private MapperFactoryBean mapperFactoryBean = new MapperFactoryBean<>(); + + public void setMapperFactoryBean(MapperFactoryBean mapperFactoryBean) { + this.mapperFactoryBean = mapperFactoryBean != null ? mapperFactoryBean : new MapperFactoryBean<>(); + } + + public ClassPathMapperScanner(BeanDefinitionRegistry registry) { + super(registry, false); + } + + public void registerFilters() { + // default include filter that accepts all classes + addIncludeFilter((metadataReader, metadataReaderFactory) -> true); + + // exclude package-info.java + addExcludeFilter((metadataReader, metadataReaderFactory) -> { + String className = metadataReader.getClassMetadata().getClassName(); + return className.endsWith("package-info"); + }); + } + + @Override + public Set doScan(String... basePackages) { + Set beanDefinitions = super.doScan(basePackages); + if (beanDefinitions.isEmpty()) { + logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); + } else { + processBeanDefinitions(beanDefinitions); + } + return beanDefinitions; + } + + private void processBeanDefinitions(Set beanDefinitions) { + GenericBeanDefinition definition; + for (BeanDefinitionHolder holder : beanDefinitions) { + definition = (GenericBeanDefinition) holder.getBeanDefinition(); + String beanClassName = definition.getBeanClassName(); + logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + + "' and '" + beanClassName + "' mapperInterface"); + + // the mapper interface is the original class of the bean + // but, the actual class of the bean is MapperFactoryBean + definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); + definition.setBeanClass(this.mapperFactoryBean.getClass()); + + logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); + definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); + } + } + + + @Override + protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { + return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent(); + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) { + if (super.checkCandidate(beanName, beanDefinition)) { + return true; + } else { + logger.warn("Skipping MapperFactoryBean with name '" + beanName + + "' and '" + beanDefinition.getBeanClassName() + "' mapperInterface" + + ". Bean already defined with the same name!"); + return false; + } + } +} diff --git a/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/register/MapperFactoryBean.java b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/register/MapperFactoryBean.java new file mode 100644 index 00000000..b2747c16 --- /dev/null +++ b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/register/MapperFactoryBean.java @@ -0,0 +1,45 @@ +package com.xpc.easyes.autoconfig.register; + +import com.xpc.easyes.core.cache.BaseCache; +import com.xpc.easyes.core.proxy.EsMapperProxy; +import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.annotation.Autowired; + +import java.lang.reflect.Proxy; + +/** + * 代理类 + *

+ * Copyright © 2021 xpc1024 All Rights Reserved + **/ +public class MapperFactoryBean implements FactoryBean { + private Class mapperInterface; + + @Autowired + private RestHighLevelClient client; + + public MapperFactoryBean() { + } + + public MapperFactoryBean(Class mapperInterface) { + this.mapperInterface = mapperInterface; + } + + @Override + public T getObject() throws Exception { + EsMapperProxy esMapperProxy = new EsMapperProxy<>(mapperInterface); + BaseCache.initCache(mapperInterface, client); + return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, esMapperProxy); + } + + @Override + public Class getObjectType() { + return this.mapperInterface; + } + + @Override + public boolean isSingleton() { + return true; + } +} diff --git a/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/register/MapperScannerRegister.java b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/register/MapperScannerRegister.java new file mode 100644 index 00000000..9298a6be --- /dev/null +++ b/easy-es-boot-starter/src/main/java/com/xpc/easyes/autoconfig/register/MapperScannerRegister.java @@ -0,0 +1,54 @@ +package com.xpc.easyes.autoconfig.register; + +import com.xpc.easyes.autoconfig.annotation.EsMapperScan; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * 注册bean + *

+ * Copyright © 2021 xpc1024 All Rights Reserved + **/ +public class MapperScannerRegister implements ImportBeanDefinitionRegistrar, ResourceLoaderAware { + private ResourceLoader resourceLoader; + + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + AnnotationAttributes mapperScanAttrs = AnnotationAttributes + .fromMap(importingClassMetadata.getAnnotationAttributes(EsMapperScan.class.getName())); + if (mapperScanAttrs != null) { + registerBeanDefinitions(mapperScanAttrs, registry); + } + } + + void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry) { + ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); + // this check is needed in Spring 3.1 + Optional.ofNullable(resourceLoader).ifPresent(scanner::setResourceLoader); + + List basePackages = new ArrayList<>(); + basePackages.addAll( + Arrays.stream(annoAttrs.getStringArray("value")) + .filter(StringUtils::hasText) + .collect(Collectors.toList())); + + scanner.registerFilters(); + scanner.doScan(StringUtils.toStringArray(basePackages)); + } +} diff --git a/easy-es-boot-starter/src/main/resources/META-INF/spring.factories b/easy-es-boot-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..67a1fd1a --- /dev/null +++ b/easy-es-boot-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +# Auto Configure +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.xpc.easyes.autoconfig.config.EsAutoConfiguration diff --git a/easy-es-boot-starter/src/main/resources/banner.txt b/easy-es-boot-starter/src/main/resources/banner.txt new file mode 100644 index 00000000..5a934406 --- /dev/null +++ b/easy-es-boot-starter/src/main/resources/banner.txt @@ -0,0 +1,7 @@ + ___ _ _ ___ + | __| __ _ ___ | || | ___ | __| ___ + | _| / _` | (_-< \_, | |___| | _| (_-< + |___| \__,_| /__/_ _|__/ _____ |___| /__/_ +_|"""""|_|"""""|_|"""""|_| """"|_| |_|"""""|_|"""""| +"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-' +--------------------------xpc--------------------------> diff --git a/easy-es-core/pom.xml b/easy-es-core/pom.xml index dcc26cdb..0d943b50 100644 --- a/easy-es-core/pom.xml +++ b/easy-es-core/pom.xml @@ -7,13 +7,13 @@ io.github.xpc1024 easy-es-parent - 0.9.2 + 0.9.3 ../easy-es-parent io.github.xpc1024 easy-es-core - 0.9.2 + 0.9.3 8 diff --git a/easy-es-parent/pom.xml b/easy-es-parent/pom.xml index 2b6393ad..7b3e6bc2 100644 --- a/easy-es-parent/pom.xml +++ b/easy-es-parent/pom.xml @@ -6,7 +6,7 @@ io.github.xpc1024 easy-es-parent - 0.9.2 + 0.9.3 easy-es-parent easy use for elastic search @@ -21,7 +21,7 @@ ../easy-es-core - ../easy-es-boot-stater + ../easy-es-boot-starter diff --git a/easy-es-sample/pom.xml b/easy-es-sample/pom.xml index f63ce8e1..6dfa0797 100644 --- a/easy-es-sample/pom.xml +++ b/easy-es-sample/pom.xml @@ -9,7 +9,7 @@ easy-es io.github.xpc1024 - 0.9.2 + 0.9.3 @@ -20,8 +20,8 @@ io.github.xpc1024 - easy-es-boot-stater - 0.9.2 + easy-es-boot-starter + 0.9.3 org.springframework.boot diff --git a/pom.xml b/pom.xml index eb83ece2..a45d1dda 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.xpc1024 easy-es - 0.9.2 + 0.9.3 easy-es easy use for elastic search