昨天把拼了一半的注解+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. LitJson报错记录

    1.float转double报错 报错类型: Max allowed object depth reached while trying to export from type System.Coll ...

  2. 5.27 NOI 模拟

    \(T1\)约定 比较水的\(dp\)题 上午想到了用区间\(dp\)求解,复杂度\(O(n^5),\)貌似没开\(long\ long\)就爆掉了 正解还是比较好想的,直接枚举从何时互不影响然后转移 ...

  3. Visual Studio Code 中文设置教程

    本文仅供学习交流使用,如侵立删!demo下载见文末 Pycharm中文设置教程 1.首先打开VisualStudioCode,点击扩展:extensions. 2.搜索chinese. 3.选择需要的 ...

  4. 使用 CSS 构建强大且酷炫的粒子动画

    粒子动画,顾名思义,就是页面上存在大量的粒子构建而成的动画.传统的粒子动画主要由 Canvas.WebGL 实现. 当然,不使用 HTML + CSS 的主要原因在于,粒子动画通常需要较多的粒子,而如 ...

  5. http、https和Cookie

    http和https http,https 都是网络传输协议 是用于网络相关传输,http走的是明文传输,https走的密文传输(内部采用对称加密以及非对称加密).对应的https安全性要高于http ...

  6. Nginx 代理Vue项目出现Invalid Host header

    说明 使用 Nginx 的 upstream 对 Vue 项目做负载均衡时,代理的地址无法访问目标地址,且页面报错: Invalid Host header(无效主机头) 分析 检查 Nginx 的 ...

  7. Python小游戏——外星人入侵(保姆级教程)第一章 03设置飞船图片 04创建Ship类

    系列文章目录 第一章:武装飞船 03:设置飞船图片 04:创建Ship类--管理飞船行为的类 一.设置飞船图片 1.注意事项 A.将图片设置为位图bmp格式最简单,因为pygame默认加载位图 B.飞 ...

  8. 【Java】学习路径33-在IDEA中使用junit单元测试运行单个方法

    首先在菜单找到 文件-项目结构 项目设置-库-"+" 选择Java 找到IDEA安装目录,打开lib/junit4.jar 的jar包,然后打开即可. 然后选择确定. 然后再项目中 ...

  9. B2. Wonderful Coloring - 2

    链接:Problem - 1551B2 - Codeforces 题意:有m个颜色,要求每种颜色内的数字各不相同,问,颜色的最大长度多少. 题解:  判断每个数字的个数,如果大于m,那么最大长度就加一 ...

  10. API设计中性能提升的10种解决方法

    api的设计涉及到的方面很多, 分类是一个基本的思考方式.如果可以形成一个系列性的文字,那就从性能开始吧. 就像任何性能一样,API 性能主要取决于如何响应不同类型的请求.例如:典型的电商场景,显示用 ...