|
@ -1,14 +1,43 @@ |
|
|
package tech.abc.platform.elasticsearch.config; |
|
|
package tech.abc.platform.elasticsearch.config; |
|
|
|
|
|
|
|
|
|
|
|
import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; |
|
|
|
|
|
import co.elastic.clients.elasticsearch.ElasticsearchClient; |
|
|
|
|
|
import co.elastic.clients.json.jackson.JacksonJsonpMapper; |
|
|
|
|
|
import co.elastic.clients.transport.ElasticsearchTransport; |
|
|
|
|
|
import co.elastic.clients.transport.rest_client.RestClientTransport; |
|
|
|
|
|
import org.apache.http.HttpHost; |
|
|
|
|
|
import org.apache.http.auth.AuthScope; |
|
|
|
|
|
import org.apache.http.auth.UsernamePasswordCredentials; |
|
|
|
|
|
import org.apache.http.client.CredentialsProvider; |
|
|
|
|
|
import org.apache.http.client.config.RequestConfig; |
|
|
|
|
|
import org.apache.http.conn.ssl.NoopHostnameVerifier; |
|
|
|
|
|
import org.apache.http.impl.client.BasicCredentialsProvider; |
|
|
|
|
|
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; |
|
|
|
|
|
import org.apache.http.ssl.SSLContextBuilder; |
|
|
|
|
|
import org.apache.http.ssl.SSLContexts; |
|
|
|
|
|
import org.elasticsearch.client.RestClient; |
|
|
|
|
|
import org.elasticsearch.client.RestClientBuilder; |
|
|
|
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
|
|
|
import org.springframework.boot.context.properties.ConfigurationProperties; |
|
|
import org.springframework.context.annotation.Bean; |
|
|
import org.springframework.context.annotation.Bean; |
|
|
import org.springframework.context.annotation.Configuration; |
|
|
import org.springframework.context.annotation.Configuration; |
|
|
import org.springframework.core.convert.converter.Converter; |
|
|
import org.springframework.core.io.ClassPathResource; |
|
|
import org.springframework.core.convert.support.DefaultConversionService; |
|
|
import org.springframework.util.StringUtils; |
|
|
import org.springframework.data.convert.ReadingConverter; |
|
|
|
|
|
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; |
|
|
|
|
|
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter; |
|
|
|
|
|
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import javax.net.ssl.SSLContext; |
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
|
import java.io.InputStream; |
|
|
|
|
|
import java.nio.file.Files; |
|
|
|
|
|
import java.nio.file.Path; |
|
|
|
|
|
import java.nio.file.Paths; |
|
|
|
|
|
import java.security.KeyManagementException; |
|
|
|
|
|
import java.security.KeyStore; |
|
|
|
|
|
import java.security.KeyStoreException; |
|
|
|
|
|
import java.security.NoSuchAlgorithmException; |
|
|
|
|
|
import java.security.cert.Certificate; |
|
|
|
|
|
import java.security.cert.CertificateException; |
|
|
|
|
|
import java.security.cert.CertificateFactory; |
|
|
import java.time.Instant; |
|
|
import java.time.Instant; |
|
|
import java.time.LocalDateTime; |
|
|
import java.time.LocalDateTime; |
|
|
import java.time.ZoneId; |
|
|
import java.time.ZoneId; |
|
@ -20,28 +49,164 @@ import java.time.ZoneId; |
|
|
* @date 2024-02-21 |
|
|
* @date 2024-02-21 |
|
|
*/ |
|
|
*/ |
|
|
@Configuration |
|
|
@Configuration |
|
|
|
|
|
|
|
|
public class ElasticSearchConfig { |
|
|
public class ElasticSearchConfig { |
|
|
|
|
|
@Value("${elasticsearch.uris}") |
|
|
|
|
|
private String hosts; |
|
|
|
|
|
|
|
|
|
|
|
@Value("${elasticsearch.username}") |
|
|
|
|
|
private String userName; |
|
|
|
|
|
|
|
|
|
|
|
@Value("${elasticsearch.password}") |
|
|
|
|
|
private String passWord; |
|
|
|
|
|
/** |
|
|
|
|
|
* 同步方式 |
|
|
|
|
|
* |
|
|
|
|
|
* @return |
|
|
|
|
|
*/ |
|
|
|
|
|
// @Bean
|
|
|
|
|
|
// public ElasticsearchClient elasticsearchClient() throws Exception {
|
|
|
|
|
|
//// HttpHost[] httpHosts = toHttpHost();
|
|
|
|
|
|
// final CredentialsProvider credentialsProvider =
|
|
|
|
|
|
// new BasicCredentialsProvider();
|
|
|
|
|
|
// credentialsProvider.setCredentials(AuthScope.ANY,
|
|
|
|
|
|
// new UsernamePasswordCredentials(userName, passWord));
|
|
|
|
|
|
//
|
|
|
|
|
|
// ClassPathResource resource = new ClassPathResource("http_ca.crt");
|
|
|
|
|
|
// CertificateFactory factory =
|
|
|
|
|
|
// CertificateFactory.getInstance("X.509");
|
|
|
|
|
|
// Certificate trustedCa;
|
|
|
|
|
|
// try (InputStream is = resource.getInputStream()) {
|
|
|
|
|
|
// trustedCa = factory.generateCertificate(is);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// KeyStore trustStore = KeyStore.getInstance("pkcs12");
|
|
|
|
|
|
// trustStore.load(null, null);
|
|
|
|
|
|
// trustStore.setCertificateEntry("ca", trustedCa);
|
|
|
|
|
|
// SSLContextBuilder sslContextBuilder = SSLContexts.custom()
|
|
|
|
|
|
// .loadTrustMaterial(trustStore, null);
|
|
|
|
|
|
// final SSLContext sslContext = sslContextBuilder.build();
|
|
|
|
|
|
//
|
|
|
|
|
|
// RestClientBuilder builder = RestClient.builder(
|
|
|
|
|
|
// new HttpHost("localhost", 9200, "https"))
|
|
|
|
|
|
// .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
|
|
|
|
|
|
// @Override
|
|
|
|
|
|
// public HttpAsyncClientBuilder customizeHttpClient(
|
|
|
|
|
|
// HttpAsyncClientBuilder httpClientBuilder) {
|
|
|
|
|
|
// return httpClientBuilder.setSSLContext(sslContext)
|
|
|
|
|
|
// .setDefaultCredentialsProvider(credentialsProvider);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
|
|
//
|
|
|
|
|
|
// RestClient restClient = builder.build();
|
|
|
|
|
|
//
|
|
|
|
|
|
// // Create the transport with a Jackson mapper
|
|
|
|
|
|
// ElasticsearchTransport transport = new RestClientTransport(
|
|
|
|
|
|
// restClient, new JacksonJsonpMapper());
|
|
|
|
|
|
//
|
|
|
|
|
|
// return new ElasticsearchClient(transport);
|
|
|
|
|
|
//// asyncClient = new ElasticsearchAsyncClient(transport);
|
|
|
|
|
|
//
|
|
|
|
|
|
// }
|
|
|
@Bean |
|
|
@Bean |
|
|
ElasticsearchConverter elasticsearchConverter(SimpleElasticsearchMappingContext mappingContext) { |
|
|
public ElasticsearchClient clientByPasswd() throws Exception { |
|
|
DefaultConversionService defaultConversionService = new DefaultConversionService(); |
|
|
ElasticsearchTransport transport = getElasticsearchTransport(userName, passWord, toHttpHost()); |
|
|
defaultConversionService.addConverter(LongToLocalDateTimeConverter.INSTANCE); |
|
|
return new ElasticsearchClient(transport); |
|
|
return new MappingElasticsearchConverter(mappingContext, defaultConversionService); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ReadingConverter |
|
|
private static SSLContext buildSSLContext() { |
|
|
static enum LongToLocalDateTimeConverter implements Converter<Long, LocalDateTime> { |
|
|
ClassPathResource resource = new ClassPathResource("http_ca.crt"); |
|
|
/** |
|
|
SSLContext sslContext = null; |
|
|
* 单例模式 |
|
|
try { |
|
|
*/ |
|
|
CertificateFactory factory = CertificateFactory.getInstance("X.509"); |
|
|
INSTANCE; |
|
|
Certificate trustedCa; |
|
|
|
|
|
try (InputStream is = resource.getInputStream()) { |
|
|
private LongToLocalDateTimeConverter() { |
|
|
trustedCa = factory.generateCertificate(is); |
|
|
|
|
|
} |
|
|
|
|
|
KeyStore trustStore = KeyStore.getInstance("pkcs12"); |
|
|
|
|
|
trustStore.load(null, null); |
|
|
|
|
|
trustStore.setCertificateEntry("ca", trustedCa); |
|
|
|
|
|
SSLContextBuilder sslContextBuilder = SSLContexts.custom() |
|
|
|
|
|
.loadTrustMaterial(trustStore, null); |
|
|
|
|
|
sslContext = sslContextBuilder.build(); |
|
|
|
|
|
} catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException | |
|
|
|
|
|
KeyManagementException e) { |
|
|
|
|
|
throw new RuntimeException("ES连接认证失败", e); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
return sslContext; |
|
|
public LocalDateTime convert(Long source) { |
|
|
} |
|
|
return Instant.ofEpochMilli(source).atZone(ZoneId.systemDefault()).toLocalDateTime(); |
|
|
private static ElasticsearchTransport getElasticsearchTransport(String username, String passwd, HttpHost...hosts) { |
|
|
|
|
|
// 账号密码的配置
|
|
|
|
|
|
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); |
|
|
|
|
|
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, passwd)); |
|
|
|
|
|
|
|
|
|
|
|
// 自签证书的设置,并且还包含了账号密码
|
|
|
|
|
|
RestClientBuilder.HttpClientConfigCallback callback = httpAsyncClientBuilder -> httpAsyncClientBuilder |
|
|
|
|
|
.setSSLContext(buildSSLContext()) |
|
|
|
|
|
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) |
|
|
|
|
|
.setDefaultCredentialsProvider(credentialsProvider); |
|
|
|
|
|
|
|
|
|
|
|
// 用builder创建RestClient对象
|
|
|
|
|
|
RestClient client = RestClient |
|
|
|
|
|
.builder(hosts) |
|
|
|
|
|
.setHttpClientConfigCallback(callback) |
|
|
|
|
|
.build(); |
|
|
|
|
|
|
|
|
|
|
|
return new RestClientTransport(client, new JacksonJsonpMapper()); |
|
|
|
|
|
} |
|
|
|
|
|
/** |
|
|
|
|
|
* 异步方式 |
|
|
|
|
|
* |
|
|
|
|
|
* @return |
|
|
|
|
|
*/ |
|
|
|
|
|
@Bean |
|
|
|
|
|
public ElasticsearchAsyncClient elasticsearchAsyncClient() { |
|
|
|
|
|
HttpHost[] httpHosts = toHttpHost(); |
|
|
|
|
|
RestClient restClient = RestClient.builder(httpHosts).build(); |
|
|
|
|
|
RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); |
|
|
|
|
|
return new ElasticsearchAsyncClient(transport); |
|
|
|
|
|
} |
|
|
|
|
|
/** |
|
|
|
|
|
* 解析配置的字符串hosts,转为HttpHost对象数组 |
|
|
|
|
|
* |
|
|
|
|
|
* @return |
|
|
|
|
|
*/ |
|
|
|
|
|
private HttpHost[] toHttpHost() { |
|
|
|
|
|
if (!StringUtils.hasLength(hosts)) { |
|
|
|
|
|
throw new RuntimeException("invalid elasticsearch configuration. elasticsearch.hosts不能为空!"); |
|
|
|
|
|
} |
|
|
|
|
|
// 多个IP逗号隔开
|
|
|
|
|
|
String[] hostArray = hosts.split(","); |
|
|
|
|
|
HttpHost[] httpHosts = new HttpHost[hostArray.length]; |
|
|
|
|
|
HttpHost httpHost; |
|
|
|
|
|
for (int i = 0; i < hostArray.length; i++) { |
|
|
|
|
|
String[] strings = hostArray[i].split(":"); |
|
|
|
|
|
httpHost = new HttpHost(strings[0], Integer.parseInt(strings[1]), "https"); |
|
|
|
|
|
httpHosts[i] = httpHost; |
|
|
} |
|
|
} |
|
|
|
|
|
return httpHosts; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// @Bean
|
|
|
|
|
|
// ElasticsearchConverter elasticsearchConverter(SimpleElasticsearchMappingContext mappingContext) {
|
|
|
|
|
|
// DefaultConversionService defaultConversionService = new DefaultConversionService();
|
|
|
|
|
|
// defaultConversionService.addConverter(LongToLocalDateTimeConverter.INSTANCE);
|
|
|
|
|
|
// return new MappingElasticsearchConverter(mappingContext, defaultConversionService);
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// @ReadingConverter
|
|
|
|
|
|
// static enum LongToLocalDateTimeConverter implements Converter<Long, LocalDateTime> {
|
|
|
|
|
|
// /**
|
|
|
|
|
|
// * 单例模式
|
|
|
|
|
|
// */
|
|
|
|
|
|
// INSTANCE;
|
|
|
|
|
|
//
|
|
|
|
|
|
// private LongToLocalDateTimeConverter() {
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Override
|
|
|
|
|
|
// public LocalDateTime convert(Long source) {
|
|
|
|
|
|
// return Instant.ofEpochMilli(source).atZone(ZoneId.systemDefault()).toLocalDateTime();
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
} |
|
|
} |
|
|