概述###

假设我们要从一个 ES 索引(相当于一张DB表)查询数据,ES表有 biz_no, type, status 等字段, 而应用对象则有属性 bizNo, type, status 等。这样,就会面临“将应用对象的属性与ES字段对应起来”的问题(实际上是个ORM)。

固然可以通过注释来说明,不过这样显得比较生硬。因为注释并不起实际作用,代码里还得写一套映射关系,就会存在注释与代码不一致的情况。 那么,是否可以将这种对应关系的注释用代码形式来解决呢? Java 注解可以解决这个问题。

实现###

定义注解####

首先定义注解类。注解类需要提供对应的ES字段名 name、类型 type 以及是否必传 required。

  • @Retention 指明注解在何时起作用,这里是在运行时。
  • @Target 指明注解应用于何种对象,这里应用于字段。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface EsField { /**
* 对应的ES字段名
*/
String name(); /**
* 对应的ES字段的值类型
* @return
*/
String type() default ""; /**
* 是否必传
*/
boolean required() default false; }

应用领域对象####

接着,将注解应用到应用领域对象。为简洁,应用领域对象只有四个字段。

@Data
public class CustomerDomain implements DomainSearch { /** 主键ID */
@EsField(name="id", required = true)
private Long id; /** 业务编号 */
@EsField(name="biz_no")
private String bizNo; /** 状态 */
@EsField(name="status", type="list")
private List<Integer> status; /** 类型 */
@EsField(name="type", type="list")
private List<Integer> type; }

注解解析器####

接着,需要提供注解解析器,将对应的映射关系转成ES查询对象的一部分。

  • 使用接口的默认方法来实现,是为了支持不同的业务类自动可以转化为ES查询串;
  • 注解解析器需要使用Java反射机制,来获取相应的字段,以及字段上的注解定义,然后根据字段的类型、值、注解定义来做相应处理;
  • 使用反射来处理字段时,由于字段一般是私有的,因此必须先设置为可访问的,处理完成后还原为不可访问;
  • EsField field = f.getAnnotation(EsField.class) 用来获取字段上的注解信息(name, type, required);Object value = f.get(customerDomain) 用来获取字段的值;字段的其他类型信息可以通过 Field 的方法拿到。
public interface DomainSearch {

  Log logger = LogFactory.getLog(DomainSearch.class);

  default String toEsQuery() {
Object customerDomain = this;
EsQuery esQuery = new EsQuery();
Field[] fields = this.getClass().getDeclaredFields();
for (Field f: fields) {
try {
if (Modifier.isStatic(f.getModifiers())) {
continue;
} f.setAccessible(true); Object value = f.get(customerDomain); if (f.getAnnotation(EsField.class) != null) {
EsField field = f.getAnnotation(EsField.class); if (field.required() && value == null) {
throw new RuntimeException("field '" + field + "' is required. value is null");
} if (isNeedOmitted(value)) {
f.setAccessible(false);
continue;
} if ((value instanceof List) && ((List)value).size() == 1) {
// 针对 List 中单个值做优化查询
esQuery = esQuery.addTermFilter(field.name(), ((List)value).get(0));
}
else {
esQuery = esQuery.addTermFilter(field.name(), value);
}
} f.setAccessible(false); } catch (Exception ex) {
logger.error("failed to build es query for field: " + f.getName(), ex);
throw new RuntimeException(ex.getCause());
}
}
return esQuery.toJsonString();
} /**
* 判断是否需要忽略该字段的查询
* @param value 字段值
* @return 是否要忽略
*/
default boolean isNeedOmitted(Object value) {
if (value == null) {
return true;
} // 空字符串搜索值忽略
if ((value instanceof String) && StringUtils.isBlank(value.toString())) {
return true;
} // 空列表串忽略
if ((value instanceof List) && ((List)value).isEmpty()) {
return true;
}
return false;
} }

限于公司的源代码不公开原则,这里 EsQuery 实现就不给出了;且 EsQuery 的实现并不是本文的重点。

小结###

通过ES搜索示例,展示了如何运用注解自动化处理领域对象属性与底层ES存储字段之间的对应关系。实际上,如果想为应用对象或组件添加某种说明或注释,不妨先想想是否可以通过注解自动化处理。注解亦可用于框架自动处理对象与组件的集成。Spring框架的Resource, Component, AOP,以及 Plugin 化设计思想等都是好的应用例子。

如果有注释,那就让它代码化。

使用Java注解自动化处理对应关系实现注释代码化的更多相关文章

  1. 如何在java注解中加入原生html标签内容

    你是否也遇到过类似的事情.想在java注解加入类似于下面这种注释: 结果出来却变成了这样 ,标签被解析了, 这怎么办呢 : 且看分解 我们在注解中直接放入下边这样的代码: <Response&g ...

  2. [转帖]java注解与注释注解区别

    https://baijiahao.baidu.com/s?id=1615942718081024481&wfr=spider&for=pc 还需要仔细看一下书的 书里面都有. jav ...

  3. 19.Java 注解

    19.Java注解 1.Java内置注解----注解代码 @Deprecated                                    //不推荐使用的过时方法 @Deprecated ...

  4. java注解(Annotation)解析

    注解(Annotation)在java中应用非常广泛.它既能帮助我们在编码中减少错误,(比如最常见的Override注解),还可以帮助我们减少各种xml文件的配置,比如定义AOP切面用@AspectJ ...

  5. JAVA 注解的几大作用及使用方法详解

    JAVA 注解的几大作用及使用方法详解 (2013-01-22 15:13:04) 转载▼ 标签: java 注解 杂谈 分类: Java java 注解,从名字上看是注释,解释.但功能却不仅仅是注释 ...

  6. JAVA 注解的几大作用及使用方法详解【转】

    java 注解,从名字上看是注释,解释.但功能却不仅仅是注释那么简单.注解(Annotation) 为我们在代码中添加信息提供了一种形式化的方法,是我们可以在稍后 某个时刻方便地使用这些数据(通过 解 ...

  7. Java注解配置

    Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明.配置的功能.注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用.包含在 java.lang.annota ...

  8. Java注解教程:自定义注解示例,利用反射进行解析

    Java注解能够提供代码的相关信息,同时对于所注解的代码结构又没有直接影响.在这篇教程中,我们将学习Java注解,如何编写自定义注解,注解的使用,以及如何使用反射解析注解. 注解是Java 1.5引入 ...

  9. Java注解教程及自定义注解

    Java注解提供了关于代码的一些信息,但并不直接作用于它所注解的代码内容.在这个教程当中,我们将学习Java的注解,如何定制注解,注解的使用以及如何通过反射解析注解. Java1.5引入了注解,当前许 ...

随机推荐

  1. 【PyQt5-Qt Designer】猜数字(小项目)

    参考:https://zhuanlan.zhihu.com/p/28287825 https://www.cnblogs.com/hhh5460/p/5174266.html 最终效果: 本次练习涉及 ...

  2. 图书管理(Loj0034)+浅谈哈希表

    图书管理 题目描述 图书管理是一件十分繁杂的工作,在一个图书馆中每天都会有许多新书加入.为了更方便的管理图书(以便于帮助想要借书的客人快速查找他们是否有他们所需要的书),我们需要设计一个图书查找系统. ...

  3. bat、sh等批处理文件(脚本文件)

    批处理文件(batch file):也被称为批处理程序或脚本,可以简化日常或重复性任务.本质是无格式的文本文件,它包含一条或多条命令.(1).bat是dos下的批处理文件,在window系统上执行的文 ...

  4. finecms同时调用子栏目和子栏目的文章怎么操作

    之前ytkah写过dedecms如何调用当前栏目的子栏目及子栏目文章,那如果是finecms如何同时调用子栏目和子栏目的文章呢? {list action=category pid=0 id=31} ...

  5. JSONObject,String,Map互相转换

    JSONObject和String相互转换 JSONObject jsonObject = new JSONObject(); JSONArray jsonArray = new JSONArray( ...

  6. Unity3D加密保护案例分享(一)

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎.通过u ...

  7. Visual Studio Code的常用快捷键

    一.Visual Studio Code简介 Visual Studio Code是个牛逼的编辑器,启动非常快,完全可以用来代替其他文本文件编辑工具.又可以用来做开发,支持各种语言,相比其他IDE,轻 ...

  8. word2vec模型评估方案

    1.word2vec参数详解 · sentences:可以是一个·ist,对于大语料集,建议使用BrownCorpus,Text8Corpus或·ineSentence构建.· sg: 用于设置训练算 ...

  9. 新手详解JAVA+数据库+JSP完成简单页面

    本篇以数据库添加为例(本例中数据库名为“xinxi”表单名字为“stud”) 准备---实体层: package entity; public class Student { private Stri ...

  10. 微信支付相关js

    import $ from "jquery" /*支付功能开始*/let ip="";let nonceStr;let appId;let mchId;let ...