枚举到底是什么

  • 结论,枚举只是一个对象列表,~~以前不理解这一点,走了一些弯路 ~~
  • 一般人印像是枚举是不可变的,但其实不太对
    • 只是枚举对象列表本身,和列表里的内容是不可变的
    • 在列表里的对象的属性,只要你没有手工指定了final 其实是可变的,是可以写setter

各种被要求写枚举

必写

以下如果你不写,新入职的员工看你代码里的if(type == 0)时,会在心里默默划过几万个草泥马

  • 业务各种type要写枚举
  • status要写枚举

这些也要写,看公司规定

  • 数据库字段
  • ES索引mapping字段

使用枚举生成ES mapping

由于枚举字段是固定的,无非就是字段名,Es类型,字段描述,理论上可以像对象继承一样弄一个父类,或是抽象类来实现通用枚举

  • 枚举不能继承,因为他本身继承了java.lang.Enum
  • 枚举是可以实现其他接口,所以我们可以通过写一个通用接口,其他Es索引的枚举实现此接口来实现自动生成mapping
  • 接口
public interface AbstractEsField {

    //字段名
    String getName();


    //字段类型
    String getEsType();

}
  • 实现类
@Getter
public  enum DataReportFieldEnum implements AbstractEsField {

    PRIMARY_KEY("primaryKey","主键",KEYWORD,false),
		;
	
	  private String name;

    private String description;

    private String esType;

    ReceivableSplitDataReportFieldEnum(String name, String description, String esType) {
        this.name = name;
        this.description = description;
        this.esType = esType;
    }	
}
  • 这样我们可玩的就多了
  • 比如根据枚举生成es mapping
  	 //生成mapping工具类
    class Util {
        //传入ES字段枚举类生成mapping XContentBuilder
        public static XContentBuilder getMappingContentBuilderByEnum(Class<? extends AbstractEsField> clazz) {
            if (!clazz.isEnum()) throw new BusinessException("must be enum");
            List<AbstractEsField> fieldList = Arrays.asList(clazz.getEnumConstants());
            if (CollectionUtils.isEmpty(fieldList)) throw new BusinessException("enum must has values");
            try {
                XContentBuilder mapping = XContentFactory.jsonBuilder(new BytesStreamOutput())
                        .startObject().field("dynamic", "false")
                        .startObject("properties");
                for (AbstractEsField item : fieldList) {
                    if (!Objects.equals(item.getEsType(), EsConstants.NESTED)) {
                        //有父字段的字段走嵌套字段处理
                        if (StringUtils.isNotBlank(item.getParentName())) continue;
                        assembMapping(mapping, item);
                    } else {
                        //嵌套字段单独处理
                        List<AbstractEsField> childFieldList = fieldList.stream().filter(x -> Objects.equals(x.getParentName(), item.getName())).collect(Collectors.toList());
                        //只支持单层嵌套
                        if (childFieldList.stream().anyMatch(x -> Objects.equals(x.getEsType(), EsConstants.NESTED))) {
                            throw new BusinessException("only support one layer nested");
                        }
                        //没有子字段忽略嵌套字段
                        if (CollectionUtils.isEmpty(childFieldList)) continue;
                        mapping.startObject(item.getName()).field(EsConstants.TYPE, item.getEsType());
                        mapping.startObject("properties");
                        for (AbstractEsField chiledField : childFieldList) {
                            assembMapping(mapping, chiledField);
                        }
                        mapping.endObject().endObject();
                    }
                }
                mapping.endObject().endObject();
                return mapping;
            } catch (IOException e) {
                throw  new BusinessException("io error",e);
            }
        }

        //传入ES字段枚举类生成mapping json String
        public static String getMappingJsonStringByEnum(Class<? extends AbstractEsField> clazz) {
            XContentBuilder mappingContentBuilder = getMappingContentBuilderByEnum(clazz);
            mappingContentBuilder.close();
            return ((BytesStream) mappingContentBuilder.getOutputStream()).bytes().utf8ToString();
        }

        //单个非嵌套字段mapping装配
        private static void assembMapping(XContentBuilder mapping, AbstractEsField esField) throws IOException {
            mapping.startObject(esField.getName()).field(EsConstants.TYPE, esField.getEsType()).field("store", "true");
            //数值类默认值处理
            if (EsConstants.NUMBER_TYPES.contains(esField.getEsType())) {
                mapping.field("null_value", EsConstants.DEFAULT_NUMBER_VALUE);
            }

            //scaled_float 默认缩放因子100
            if (Objects.equals(esField.getEsType(), EsConstants.SCALED_FLOAT)) {
                mapping.field("scaling_factor", EsConstants.DEFAULT_SCALED_FLOAT_FACTOR);
            }

            //date 默认format处理
            if (Objects.equals(esField.getEsType(), EsConstants.DATE)) {
                mapping.field("format", EsConstants.DEFAULT_DATE_FORMAT);
            }
            mapping.endObject();
        }
		    public static void main(String[] args) {
       			System.out.println(Util.getMappingJsonStringByEnum(DataReportFieldEnum.class));
   			}

}
  • 为了统一我们可以把这个类放到AbstractEsField里

  • end ,枚举生成数据库相关代码也一样的思路,生成的代码,总是会比自己写的要好用,不会出错