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 ...
随机推荐
- python对象的独有功能与面向对象的特征
目录 对象的独有功能 动静态方法 面向对象的特征 面向对象的的三大特征 继承的本质 不继承的名字查找顺序 单继承的名字查找顺序 多继承的名字查找顺序 经典类与新式类 派生方法 对象的独有功能 1.定义 ...
- GS2107-WTBD 用什么软件为什么新建不了GS系列
1.GS系列GOT必须使用官网上的新软件,资料下载-软件下载-GOT 1000 & GOT 2000 & GOT Simple 画面设计软件,下载安装后,机种选择GS系列即可. 2.在 ...
- 参考MySQL Internals手册,使用Golang写一个简单解析binlog的程序
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. MySQL作为最流行的开源关系型数据库,有大量的拥趸.其生态已经相当完善,各项特性在圈内都有大量研究.每次新特性发布,都会 ...
- 【AGC】引导用户购买提升用户留存率
借助AGC的云数据库.云托管.应用内消息.App Linking等服务,您可以给不同价值用户设置不同的优惠套餐活动,引导用户持续购买,增强用户黏性.判断用户价值,发送营销短信,引导用户参与营销活动,提 ...
- 【游记】CSP 2021 J2
这次是第一次参加CSP的复赛,所以考的就很LJ. \(DAY-\infty\) 到 \(DAY-14\) 知道了自己苟过了初赛,像个SB一样. (我初赛66分,旁边那位63.5,cao着线过去的) \ ...
- 【Java】学习路径46-两种创建多线程的方法、以及在匿名内部类创建线程
两种方法: 1.创建一个继承自Thread的线程类,然后再main(不限)中构造这个线程类对象.方法在之前讲过. 2.创建一个使用Runnable接口的线程类,然后在main(不限)中构造这个Runn ...
- Electron学习(四)之应用程序打包
highlight: a11y-dark 写在前面 人真的是会变得越来越懒的,也正是人的惰性吧,真的是很讽刺. 关于这个应用程序的开发,断更了很久,但是代码部分还算没落下吧,终于在周一.周二终把这个应 ...
- 第三课:nodejs npm和vue
1.安装node js 2.node js给windows提供了一个可以直接执行js的环境{node提供翻译} 3.npm是包管理器 a.npm是nodejs的组成部分 b.管 包(package) ...
- KingbaseES V8R3集群运维案例之---用户自定义表空间管理
案例说明: KingbaseES 数据库支持用户自定义表空间的创建,并建议表空间的文件存储路径配置到数据库的data目录之外.本案例复现了,当用户自定义表空间存储路径配置到data下时,出现的故障问 ...
- Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点
Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...