Java注解(4):一个真实的Elasticsearch案例
昨天把拼了一半的注解+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案例的更多相关文章
- Java注解开发与应用案例
Java注解开发与应用案例 Annotation(注解)是JDK5.0及以后版本引入的,可以对包.类.属性.方法的描述,给被述对象打上标签,被打上标签后的类.属性.方法将被赋予特殊的“功能”:打个比喻 ...
- Java注解小记
java注解是jdk1.5以后新出的特性,注解提升了Java语言的表达能力,有效地实现了应用功能和底层功能的分离,框架/库的程序员可以专注于底层实现. 1.Java内置注解 主要有三个: @Overr ...
- java基础---->java注解的使用(一)
注解是众多引入到Java SE5中的重要的语言变化之一.它为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据.今天我们就开始学习一下java中注解的知识. j ...
- Java 注解指导手册 – 终极向导
原文链接 原文作者:Dani Buiza 译者:Toien Liu 校对:深海 编者的话:注解是java的一个主要特性且每个java开发者都应该知道如何使用它. 我们已经在Java Code Gee ...
- 分享知识-快乐自己:全面解析 java注解实战指南
请你在看这篇文章时,不要感到枯燥,从头到尾一行行看,代码一行行读,你一定会有所收获的. 问: 为什么学习注解? 学习注解有什么好处? 学完能做什么? 答: 1):能够读懂别人的代码,特别是框架相关的代 ...
- 《Java基础知识》Java注解"@"详解
Java注解含义: Java注解,顾名思义,注解,就是对某一事物进行添加注释说明,会存放一些信息,这些信息可能对以后某个时段来说是很有用处的.Java注解又叫java标注,java提供了一套机制,使得 ...
- 【java提高】(16)---java注解(Annotation)
java提高(16)---java注解 注解含义注解是JDK1.5之后才有的新特性,它相当于一种标记,在程序中加入注解就等于为程序打上某种标记,之后又通过类的反射机制来解析注解. 一.JDK自带注解 ...
- Java 注解指导手册(上)
编者的话:注解是java的一个主要特性且每个java开发者都应该知道如何使用它. 我们已经在Java Code Geeks提供了丰富的教程, 如Creating Your Own Java A ...
- java 注解 Annontation
什么是注解? 对于很多初次接触的开发者来说应该都有这个疑问?Annontation是Java5开始引入的新特征,中文名称叫注解.它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metada ...
随机推荐
- Vue ref属性 && props配置项
1 // # ref属性: 2 // # 1.用来给元素或者子组件注册引用信息(id的替代者) 3 // # 2.应用在html标签上获取的是真实的DOM元素,应用在组件标签上是组件实例对象(vc) ...
- 【原创】Magisk Root隐藏模块 Shamiko安装
本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! Root隐藏模块 Shamiko安装 操 ...
- Word 分页符怎么使用
当一页内容输入完之后,还留有很多空白区域没有填写,一直按回车键跳转到下一页显得复杂,并且回车键经过的地方都是段落. 可以手动添加分页符,使当前页跳转到下一页. 也可以使用快捷键Ctrl + Enter ...
- [网鼎杯2018]Unfinish-1|SQL注入|二次注入
1.进入题目之后只有一个登录界面,检查源代码信息并没有发现有用的信息,尝试万能密码登录也不行,结果如下: 2.进行目录扫描,发现了注册界面:register.php,结果如下: 3.那就访问注册界面, ...
- 【深度学习】DNN房价预测
前言 我们使用深度学习网络实现波士顿房价预测,深度学习的目的就是寻找一个合适的函数输出我们想要的结果.深度学习实际上是机器学习领域中一个研究方向,深度学习的目标是让机器能够像人一样具有分析学习的能力, ...
- flask-restful使用指南
flask-restful是flask模块的一个扩展,能够快速构建restful风格的api.对于其他的扩展也有很高的兼容性. 安装flask_restful pip install flask_re ...
- linux --stdin 管道 标准输入重定向
linux --stdin 标准输入重定向 --stdin This option is used to indicate that passwd should read the new passwo ...
- 拥挤的奶牛题解---队列优化DP---DD(XYX)的博客
拥挤的奶牛 时间限制: 1 Sec 内存限制: 128 MB 题目描述 FJ的n头奶牛(1<=n<=50000)在被放养在一维的牧场.第i头奶牛站在位置x(i),并且x(i)处有一个高度 ...
- 【Java】学习路径51-线程组
平时创建线程的时候,系统会默认为线程分组. 我们可以使用 ThreadGroup tg1 = t1.getThreadGroup(); 取得t1的线程组对象. 然后使用getName获得线程组名称. ...
- 深入分析JVM执行引擎
程序和机器沟通的桥梁 一.闲聊 相信很多朋友在出国旅游,或者与外国友人沟通的过程中,都会遇到语言不通的烦恼.这时候我们就需要掌握对应的外语或者拥有一部翻译机.而笔者只会中文,所以需要借助一部翻译器才能 ...