昨天把拼了一半的注解+Elasticsearch積木放下了,因為東西太多了拼不好,還容易亂,休息了一晚上接著來,
接著昨天,創建elasticsearch檔案注解(相當于資料表的注解):
/** * elastic檔案注解,定義每個elasticsearch檔案上的屬性 * * @author xiangwang */ @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE }) public @interface Document { String index(); String type() default "_doc"; boolean useServerConfiguration() default false; short shards() default 1; short replicas() default 0; String refreshInterval() default "1s"; String indexStoreType() default "fs"; }
然后再創建elasticsearch檔案(相當于資料表):
/** * elastic檔案物件 * * @author xiangwang */ @Document(index = "document", type = "_doc", shards = 1, replicas = 0) public class ElasticDocument { private static final long serialVersionUID = 2879048112350101009L; // 檔案編碼 @DocField(name = "guid", type = FieldType.Keyword) protected String guid = ""; // 標題 @DocField(name = "title", type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word") protected String title = ""; // 檔案創建時間(資源實際創建時間) @DocField(name = "createtime", type = FieldType.Long) protected long createtime; // 檔案更新時間(資源實際更新時間) @DocField(name = "updatetime", type = FieldType.Long) protected long updatetime; public ElasticDocument() { } public String getGuid() { return guid; } public void setGuid(String guid) { this.guid = guid; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public long getCreatetime() { return createtime; } public void setCreatetime(long createtime) { this.createtime = createtime; } public long getUpdatetime() { return updatetime; } public void setUpdatetime(long updatetime) { this.updatetime = updatetime; } @Override public String toString() { return String.format("{\"guid\":\"%s\", \"title\":\"%s\", \"createtime\":%d, " + "\"updatetime\":%d}", guid, title, createtime, updatetime); } }
這里面的@Document就是剛才創建的檔案注解,
最后,創建一個真正的執行者,就由它來完成所有材料的拼裝:
/** * ElasticDao * * @author xiangwang */ @Component public class ElasticDao { // ElasticConfiguration中定義的Bean物件 @Autowired private RestHighLevelClient client; /** * 索引是否存在 * */ public boolean indexExist(final String index) { try { return client.indices().exists(new GetIndexRequest(index), RequestOptions.DEFAULT); } catch (IOException e) { System.out.println("index exist exception"); } return false; } /** * 決議類注解,獲取包括父類欄位在內的所有欄位 * 因為決議的時候,會把父類及自身的一些額外欄位給決議進去 * 如logger、serialVersionUID等 * 所以需要把這些無用的欄位排除掉 * 這里不存在繼承,所以直接呼叫clazz.getDeclaredFields() * 另外,如果存在繼承關系,該怎么處理呢?(可以思考一下) * */ public static List<Field> getAllDeclaredFields(Class<?> clazz) { return new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())); } /** * 創建索引,前面都是為了實作它作準備 * 這里會通過注解,一路決議檔案的欄位,拼接成可執行的腳本交給elasticsearch的api去執行 * */ public boolean createIndex(final String index, final Class<?> clazz) { try { Document document = (Document) clazz.getAnnotation(Document.class); int shards = document.shards(); int replicas = document.replicas(); if (indexExist(index)) { return false; } CreateIndexRequest request = new CreateIndexRequest(index); request.settings(Settings.builder() .put("index.number_of_shards", shards) .put("index.number_of_replicas", replicas) ); StringBuilder builder = new StringBuilder(); builder.append("{\n"); builder.append(" \"properties\": {\n"); List<Field> list = getAllDeclaredFields(clazz); int length = list.size(); for (int i = 0; i < length; i++) { DocField docField = list.get(i).getAnnotation(DocField.class); if (null == docField) { continue; } builder.append(" \"").append(docField.name()).append("\" : {\n"); builder.append(" \"type\" : \"").append(docField.type().value).append("\""); if (docField.index()) { builder.append(", \n"); builder.append(" \"index\" : ").append(docField.index()); } if (docField.fielddata()) { builder.append(", \n"); builder.append(" \"fielddata\" : ").append(docField.fielddata()); } if (docField.store()) { builder.append(", \n"); builder.append(" \"store\" : ").append(docField.store()); } if (StringUtils.isNotBlank(docField.analyzer())) { builder.append(", \n"); builder.append(" \"analyzer\" : \"").append(docField.analyzer()).append("\""); } if (StringUtils.isNotBlank(docField.format())) { builder.append(", \n"); builder.append(" \"format\" : \"").append(docField.format()).append("\""); } if (StringUtils.isNotBlank(docField.searchAnalyzer())) { builder.append(", \n"); builder.append(" \"search_analyzer\" : \"").append(docField.searchAnalyzer()).append("\""); } if (StringUtils.isNotBlank(docField.pattern())) { builder.append(", \n"); builder.append(" \"pattern\" : \"").append(docField.pattern()).append("\""); } if (StringUtils.isNotBlank(docField.normalizer())) { builder.append(", \n"); builder.append(" \"normalizer\" : \"").append(docField.normalizer()).append("\""); } if (i == length -1) { builder.append("\n }\n"); } else { builder.append("\n }, \n"); } } builder.append(" }\n"); builder.append("}\n"); request.mapping(JSON.parseObject(builder.toString()).toJSONString(), XContentType.JSON); CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT); boolean acknowledged = response.isAcknowledged(); return acknowledged; } catch (IOException e) { System.out.println("create index exception"); } return false; } }
好了,現在該搭個臺子讓這個執行者上臺表演了:
/** * 索引Service實作 * * @author xiangwang */ @Service public class IndexService { @Resource private ElasticDao elasticDao; /** * 索引初始化 * * 這個方法可以在啟動應用時呼叫,可以在介面中呼叫,也可以在main方法中呼叫 */ @PostConstruct private void initIndex() { boolean flag = false; // 創建一個名為Test的索引 if (!elasticDao.indexExist("Test")) { flag = elasticDao.createIndex("Test", ElasticDocument.class); if (flag) { System.out.println("create Test index success"); } else { System.out.println("create Test index failure"); } } else { System.out.println("Test index exist"); } } }
這就是整個注解結合Elasticsearch的真實案例,
其實這玩意一開始只是作為代碼里面的小工具,但到后來隨著需求越來越多,越來越變態,在我們后來的系統中它發展成了一個內部的小系統,可以通過管理后臺的功能按鈕來動態創建、修改、洗掉Elasticsearch的索引和檔案,以及匯出、匯入資料等等功能,既非常強大,也非常方便,
我想,那些目前主流開發的框架也都是這么從小做起,一點點發展起來的吧,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/515135.html
標籤:Java
上一篇:【HDLBits刷題日記】01 Getting Started & Basics
下一篇:__slots__
