Spring Boot集成OpenSearch遇save方法异常及版本匹配问题
问题现象
- 调用
save(T t)方法时,数据已成功写入OpenSearch,但抛出响应体解析异常:java.lang.RuntimeException: Unable to parse response body for Response{requestLine=PUT /game-index1/_doc/2009?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 201 Created}
findById、findAll等GET方法可正常执行,仅save方法触发异常- 应用启动时提示版本不匹配:
Version mismatch in between Elasticsearch Client and Cluster: 7.12.1 - 2.7.0
实际集群为OpenSearch,不存在7.x版本
环境配置
pom.xml依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> <version>2.5.1</version> </dependency> <dependency> <groupId>org.opensearch.client</groupId> <artifactId>opensearch-rest-high-level-client</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>org.opensearch</groupId> <artifactId>opensearch</artifactId> <version>1.1.0</version> </dependency>
OpenSearch配置类
@Configuration @EnableElasticsearchRepositories(basePackageClasses = CricketerRepo.class) @ComponentScan(basePackageClasses = OpenSearchConfig.class) public class OpenSearchConfig { @Bean public RestHighLevelClient client() { return new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"))); } }
注:已禁用OpenSearch登录验证
文档类
@Document(indexName = "game-index1") public class Cricketer { @Id private String cID; private String cName; private String cRole; private String cCountry; }
仓库类
@Repository public interface CricketerRepo extends ElasticsearchRepository<Cricketer, String> { }
服务类方法
@Autowired CricketerRepo repository; public Cricketer addCricketer(Cricketer cricketer) { return repository.save(cricketer); // 异常发生在此行 }
问题原因与解决方案
核心原因
Spring Boot 2.5.1的spring-boot-starter-data-elasticsearch依赖的Elasticsearch客户端版本为7.12.1,与OpenSearch 2.7.0版本跨度较大,两者响应格式存在差异,导致save操作的响应体无法被旧版客户端解析。虽然OpenSearch兼容部分Elasticsearch API,但版本不匹配会引发解析类异常。
具体解决步骤
1. 统一依赖版本
使用OpenSearch官方提供的Spring Boot Starter替代原有的Elasticsearch starter,确保依赖版本与集群版本(2.7.0)完全一致:
<!-- 移除原有spring-boot-starter-data-elasticsearch、opensearch-rest-high-level-client、opensearch依赖 --> <dependency> <groupId>org.opensearch.client</groupId> <artifactId>opensearch-spring-boot-starter</artifactId> <version>2.7.0</version> </dependency>
2. 调整客户端配置类
改用OpenSearch官方客户端替代RestHighLevelClient:
@Configuration @EnableElasticsearchRepositories(basePackageClasses = CricketerRepo.class) public class OpenSearchConfig { @Value("${opensearch.host:localhost}") private String host; @Value("${opensearch.port:9200}") private int port; @Bean public OpenSearchClient openSearchClient() { RestClient restClient = RestClient.builder(new HttpHost(host, port, "http")).build(); return new OpenSearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper())); } }
3. 适配仓库接口
统一使用OpenSearch官方的Repository接口(部分版本兼容ElasticsearchRepository,但推荐使用官方接口):
@Repository public interface CricketerRepo extends OpenSearchRepository<Cricketer, String> { }
4. 验证依赖一致性
通过Maven依赖树工具检查所有OpenSearch相关依赖的版本,确保无版本冲突,彻底消除版本不匹配警告。
内容的提问来源于stack exchange,提问作者Ruthvik Manapragada

