美文网首页
Spring中Elasticsearch使用Spel动态创建Do

Spring中Elasticsearch使用Spel动态创建Do

作者: dothetrick | 来源:发表于2020-04-18 17:12 被阅读0次

    1 使用场景

    在一些项目中,需要在程序中根据条件,动态生成es的index,达到整理数据的目的。
    例如,大数据量的系统日志,需要按天分index,这时就需要动态生成Index。

    2 Spel动态生成Index

    这里使用spring-data-elasticsearchElasticsearchRestTemplate操作es,版本为3.2.0。

    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-elasticsearch</artifactId>
        <version>3.2.0.RELEASE</version>
    </dependency>
    

    在使用@Document注解标识POJO对象时,可以指定静态IndexName。

    @Document(indexName = "indexName", type = "logger")
    

    但是要如何动态生成index呢?这里使用Spel

    Spel的全称是Spring Expression Language,是spring的一种表达式语言,功能很强大,官方网址

    使用Spel可以在注解中通过表达式调用Bean的方法来给参数赋值。

    所以动态生成的思路就是创建一个index的生成器,在@Ducument中调用生成器方法给indexName属性赋值。

    生成器实例如下:

    @Component("indexNameGenerator")
    public class IndexNameGenerator {
        public String commonIndex() {
            //根据日期生成index
            String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            return "collectlog_" + date;
        }
    }
    

    Document类的实例如下:

    @NoArgsConstructor
    @Data
    @Document(indexName = "#{@indexNameGenerator.commonIndex()}", type = "logger")
    public class ESDocument {
        @Field(analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
        private String content;
        private String cluster;
        private long date = LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
        private String path;
        private String ip;
        private String level;
    }
    

    可以看到,在@Document注解中,调用了indexNameGenerator.commonIndex(),方法获取每天的Index。
    该方法会在每次新增数据的时候被调用。

    3 一些注意事项

    要注意的是Spel使用context获取对应的Bean Resolver,如果项目运行中报异常,

    org.springframework.expression.spel.SpelEvaluationException: 
    EL1057E: No bean resolver registered in the context to resolve access to bean 'indexNameGenerator'
    

    这个原因主要是Spel中使用的spring context有问题造成的,可以断点到,SpelExpression#getValue方法中调试问题。

    org.springframework.expression.spel.standard.SpelExpression#getValue(org.springframework.expression.EvaluationContext, java.lang.Class<T>) 
    

    在ES使用时,如果是手动创建的ElasticsearchRestTemplate,在创建实例时一定要设置ElasticsearchConverter,不然会报上述异常。

    ElasticsearchConverter可以使用springboot autoconfig中生成的Bean,里面已注入正确的ApplicationContext,实例如下:

    @EnableConfigurationProperties(ESProperties.class)
    @Service("elasticSearchHandlerFactory")
    public class ElasticSearchHandlerFactory {
        @Resource
        ESProperties esProperties;
    
        /**
         * 已经在elastic autoconfig 中创建,可以直接使用
         */
        @Resource
        ElasticsearchConverter elasticsearchConverter;
    
        public ElasticsearchRestTemplate getHandler() {
            ESProperties.DbConfig dbConfig = esProperties.getDbList().get("c1");
            final ClientConfiguration configuration = ClientConfiguration.builder()
                    .connectedTo(dbConfig.getHostAndPort())
                    .withBasicAuth(dbConfig.getUsername(), dbConfig.getPassword())
                    .build();
            RestHighLevelClient client = RestClients.create(configuration).rest();
            return new ElasticsearchRestTemplate(client, elasticsearchConverter);
        }
    }
    

    以上内容属个人学习总结,如有不当之处,欢迎在评论中指正

    相关文章

      网友评论

          本文标题:Spring中Elasticsearch使用Spel动态创建Do

          本文链接:https://www.haomeiwen.com/subject/cdyivhtx.html