You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data Elasticsearch中@Mapping与@Setting路径SpEL无法解析怎么办

当前Spring Data Elasticsearch仅对@Document注解的相关属性内置了SpEL解析能力,@Setting、@Mapping注解的路径属性默认没有做SpEL解析处理,所以表达式会被当成普通资源路径读取,才会抛出找不到资源的报错。

通过自定义Elasticsearch持久化实体和映射上下文,手动添加SpEL解析逻辑即可实现需求,具体实现步骤如下:

1. 自定义支持SpEL解析的持久化实体

import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class SpelSupportedElasticsearchPersistentEntity<T> extends SimpleElasticsearchPersistentEntity<T> implements ApplicationContextAware {

    private static final SpelExpressionParser PARSER = new SpelExpressionParser();
    private ApplicationContext applicationContext;
    private StandardEvaluationContext evaluationContext;

    public SpelSupportedElasticsearchPersistentEntity(TypeInformation<T> information) {
        super(information);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        this.evaluationContext = new StandardEvaluationContext();
        evaluationContext.setBeanResolver((context, beanName) -> applicationContext.getBean(beanName));
    }

    @Override
    public String getSettingPath() {
        String originalPath = super.getSettingPath();
        return parseSpelIfNecessary(originalPath);
    }

    @Override
    public String getMappingPath() {
        String originalPath = super.getMappingPath();
        return parseSpelIfNecessary(originalPath);
    }

    private String parseSpelIfNecessary(String value) {
        if (value != null && value.startsWith("#{")) {
            return PARSER.parseExpression(value).getValue(evaluationContext, String.class);
        }
        return value;
    }
}

2. 自定义映射上下文,替换默认实体创建逻辑

import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.util.TypeInformation;

public class SpelSupportedElasticsearchMappingContext extends SimpleElasticsearchMappingContext {
    @Override
    protected <T> ElasticsearchPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
        SpelSupportedElasticsearchPersistentEntity<T> entity = new SpelSupportedElasticsearchPersistentEntity<>(typeInformation);
        entity.setApplicationContext(getApplicationContext());
        return entity;
    }
}

3. 注册自定义映射上下文到Spring容器

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchMappingContext;

@Configuration
public class ElasticsearchConfig {

    @Bean
    public ElasticsearchMappingContext elasticsearchMappingContext() {
        return new SpelSupportedElasticsearchMappingContext();
    }

    // 保留你原有配置Bean即可
    @Bean
    public String mySettingsFilePath() {
        return "classpath:index-settings.json";
    }
}

注意事项

  • 该实现同时支持@Setting的settingPath和@Mapping的mappingPath属性的SpEL解析,用法和@Document注解中的SpEL用法完全一致
  • 如果SpEL表达式中引用了其他Bean,需要确保对应Bean的初始化顺序早于ElasticsearchMappingContext,避免解析时找不到Bean
  • 该实现兼容Spring Data Elasticsearch 4.0+所有版本,低版本调整对应方法名即可使用

内容的提问来源于stack exchange,提问作者Андрей Палкин

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 16:57:05