昨天把拼了一半的注解+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的索引和文档,以及导出、导入数据等等功能,既非常强大,也非常方便。

我想,那些目前主流开发的框架也都是这么从小做起,一点点发展起来的吧。

Java注解(4):一个真实的Elasticsearch案例的更多相关文章

  1. Java注解开发与应用案例

    Java注解开发与应用案例 Annotation(注解)是JDK5.0及以后版本引入的,可以对包.类.属性.方法的描述,给被述对象打上标签,被打上标签后的类.属性.方法将被赋予特殊的“功能”:打个比喻 ...

  2. Java注解小记

    java注解是jdk1.5以后新出的特性,注解提升了Java语言的表达能力,有效地实现了应用功能和底层功能的分离,框架/库的程序员可以专注于底层实现. 1.Java内置注解 主要有三个: @Overr ...

  3. java基础---->java注解的使用(一)

    注解是众多引入到Java SE5中的重要的语言变化之一.它为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据.今天我们就开始学习一下java中注解的知识. j ...

  4. Java 注解指导手册 – 终极向导

    原文链接 原文作者:Dani Buiza 译者:Toien Liu  校对:深海 编者的话:注解是java的一个主要特性且每个java开发者都应该知道如何使用它. 我们已经在Java Code Gee ...

  5. 分享知识-快乐自己:全面解析 java注解实战指南

    请你在看这篇文章时,不要感到枯燥,从头到尾一行行看,代码一行行读,你一定会有所收获的. 问: 为什么学习注解? 学习注解有什么好处? 学完能做什么? 答: 1):能够读懂别人的代码,特别是框架相关的代 ...

  6. 《Java基础知识》Java注解"@"详解

    Java注解含义: Java注解,顾名思义,注解,就是对某一事物进行添加注释说明,会存放一些信息,这些信息可能对以后某个时段来说是很有用处的.Java注解又叫java标注,java提供了一套机制,使得 ...

  7. 【java提高】(16)---java注解(Annotation)

    java提高(16)---java注解 注解含义注解是JDK1.5之后才有的新特性,它相当于一种标记,在程序中加入注解就等于为程序打上某种标记,之后又通过类的反射机制来解析注解. 一.JDK自带注解 ...

  8. Java 注解指导手册(上)

      编者的话:注解是java的一个主要特性且每个java开发者都应该知道如何使用它.   我们已经在Java Code Geeks提供了丰富的教程, 如Creating Your Own Java A ...

  9. java 注解 Annontation

    什么是注解? 对于很多初次接触的开发者来说应该都有这个疑问?Annontation是Java5开始引入的新特征,中文名称叫注解.它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metada ...

随机推荐

  1. Ubuntu14.04或16.04下普通用户的root权限获得

    Ubuntu系统默认不允许使用root登录,因此初始root帐户是不能使用的,需要在普通账户下利用sudo权限修改root密码.然后以root帐户进行相关操作. 具体操作: 1.打开系统,用普通帐户登 ...

  2. RestTemplate上传文件

    1.上传的文件是File类型 如果文件保存在本地,即可以通过File file = new File(path) 或者 文件路径地址获取到指定文件 public String uploadFile(F ...

  3. 技术分享 | Prometheus+Grafana监控MySQL浅析

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 简介 Prometheus 一套开源的监控&报警&时间序列数据库的组合,通常 Kubernetes 中都会 ...

  4. 出票系统:根据淡旺季的月份和年龄,打印票价[课后练习] 出票系统:根据淡旺季的月份和年龄,打印票价[课后练习] 4 10旺季: 4 10旺季: 成人(18-60) : 60 成人(18-60):60 儿童(<18) :半价 儿童(<18):半价 老人(>60) :1/3 老人(>60):1/3 淡季: 淡季: 成人: 40 成人:40 其他: 20 其他:20

    用if适合新手练习 package LianXiTi;import java.util.Scanner;public class first2 {// 出票系统:根据淡旺季的月份和年龄,打印票价[课后 ...

  5. 使用.NET简单实现一个Redis的高性能克隆版(三)

    译者注 该原文是Ayende Rahien大佬业余自己在使用C# 和 .NET构建一个简单.高性能兼容Redis协议的数据库的经历. 首先这个"Redis"是非常简单的实现,但是他 ...

  6. 迅捷Flutter图片浏览软件

    下载地址: https://github.com/patton88/agile_flutter_picture_show/raw/master/agile_flutter_picture_show_v ...

  7. MQ系列3:RocketMQ 架构分析

    MQ系列1:消息中间件执行原理 MQ系列2:消息中间件的技术选型 1 背景 我们前面两篇对主流消息队列的基本构成和技术选型做了详细的分析.从本篇开始,我们会专注当下主流MQ之一的RocketMQ. 从 ...

  8. vue.js及H5常见跨域问题解决方案

    一.原生H5跨域问题解决方案 1.live-server 代理解决 首先在有node.js环境下,打开命令行工具,输入 npm install live-server -g 全局安装全局安装 live ...

  9. PicGo+GitHub 图床搭建

    前言 用GitHub搭建图床,在很久之前我就有了解,但由于市面上有挺多免费的图床,比如我之前一直在用的 路过图床,所以一直懒得动手搭建GitHub图床.一直到前两天我在完善博客的相册时,发现 路过图床 ...

  10. Java循环解析

    Java循环解析 while循环(先判断) int i=0; while (i<100){    i++;    System.out.println(i); } DoWhile循环(先执行,后 ...