记录供个人回看,有问题欢迎讨论
依赖版本:
<!--elastic-search java客户端-->
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.15.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
前置知识
在es8client中,构建es client时可以自定义请求响应拦截器
var restClient = RestClient
.builder(HttpHost.create("serverUrl"))
.setDefaultHeaders(new Header[]{
// ...
})
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
.addInterceptorFirst((HttpRequestInterceptor) (request, context) -> {
// 请求拦截器逻辑
})
.addInterceptorLast((HttpResponseInterceptor) (response, context) -> {
// 响应拦截器逻辑
})
)
.build();
问题处理思路
-
用拦截器编辑请求头和响应头
-
编辑请求头让es服务器兼容
-
编辑响应头让es客户端兼容
【兼容性问题一】 Missing [X-Elastic-Product] header(406)
报错信息类似:
co.elastic.clients.transport.TransportException: [es/search] Missing [X-Elastic-Product] header. Please check that you are connecting to an Elasticsearch instance, and that any networking filters are preserving that header.
这个就是响应头缺少"X-Elastic-Product"这个字段,es8客户端会验证响应是否有X-Elastic-Product=Elasticsearch标头
解决方法是编辑响应头:
var restClient = RestClient
.builder(HttpHost.create(serverUrl))
.setDefaultHeaders(new Header[]{
...
})
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
.setDefaultCredentialsProvider(credentialsProvider)
.addInterceptorLast((HttpResponseInterceptor)
(response, context) ->
response.addHeader("X-Elastic-Product", "Elasticsearch"))
) // 这部分为了避免旧版本406报错(如果es更新到了8.xx,把这个去掉即可)
.build();
【兼容性问题2】 Invalid media-type value on headers [Accept, Content-Type]
报错信息类似:
[es/create] failed: [media_type_header_exception] Invalid media-type value on headers [Accept, Content-Type]
这个同上,编辑请求头:
var restClient = RestClient
.builder(HttpHost.create(serverUrl))
.setDefaultHeaders(new Header[]{
})
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
.setDefaultCredentialsProvider(credentialsProvider)
.addInterceptorFirst((HttpRequestInterceptor) (request, context) -> {
// 这里主动编辑请求头,避免兼容性问题报错
// 在es8中,默认的请求头 Accept 字段为:
// Accept: application/vnd.elasticsearch+json; compatible-with=8
// 访问低版本es集群有可能出现
// [es/create] failed:
// [media_type_header_exception] Invalid media-type value
// on headers [Accept, Content-Type]
// 通过拦截器编辑请求头以避免此错误!
request.setHeader("Accept", "application/json");
})
) // 这部分为了避免旧版本406报错(如果es更新到了8.xx,把这个去掉即可)
.build();
一个示例
// 账号密码认证 Provider:
var credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(
username, // 用户名
password // 密码
));
RestClient restClient = RestClient
.builder(HttpHost.create(serverUrl))
.setDefaultHeaders(new Header[]{
new BasicHeader("Content-Type", "application/json; charset=utf-8"),
new BasicHeader("Accept", "application/json")
// 暂时不用token认证
// new BasicHeader("Authorization", "ApiKey " + apiKey)
})
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
.setDefaultCredentialsProvider(credentialsProvider)
.addInterceptorFirst((HttpRequestInterceptor) (request,context) -> {
// 这里主动编辑请求头,避免兼容性问题报错
// 在es8中,默认的请求头 Accept 字段为:
// Accept: application/vnd.elasticsearch+json; compatible-with=8
// 访问低版本es集群有可能出现
// [es/create] failed:
// [media_type_header_exception] Invalid media-type value
// on headers [Accept, Content-Type]
// 通过拦截器编辑请求头以避免此错误!
request.setHeader("Accept", "application/json");
})
.addInterceptorLast((HttpResponseInterceptor)
(response, context) ->
response.addHeader("X-Elastic-Product", "Elasticsearch"))
) // 这部分为了避免旧版本406报错(如果es更新到了8.xx,把这个去掉即可)
.build()
参考: