遇到2个问题:
1.我的Elasticsearch安装了X-pack插件,现有的Spring-data-elasticsearch不支持x-pack。
2.我的Elasticsearch开启了SSL验证,在连接时需要设置。
ElasticsearchTemplate是Spring-data-elasticsearch包封装好的Elasticsearch客户端对象,里面包含了Elasticsearch的各种基本操作,在集成到我的项目过程中发现Spring-data-elasticsearch并不支持安装了X-pack插件的Elasticsearch,主要是x-pack需要用户名密码认证。查看源码发现org.springframework.data.elasticsearch.core.ElasticsearchTemplate的构造函数需要一个org.elasticsearch.client.Client,于是就想我自己实现一个Client,用它来构造ElasticsearchTemplate不就行了嘛。
<!-- 自己实例化一个client -->
<bean id="elasticSearchClient" class="com.xxx.xxx.elastic.TransportClientFactoryBean">
<property name="clusterName" value="${esserver.cluster.name}"></property>
<property name="nodes" value="${esserver.cluster.nodes}"></property>
<property name="port" value="${esserver.cluster.port}"></property>
<property name="user" value="${esserver.cluster.user}"></property>
<property name="pass" value="${esserver.cluster.pass}"></property>
<property name="clientSslEnabled" value="${esserver.cluster.clientSslEnabled}"></property>
</bean>
<!-- 实例化的client作为ElasticsearchTemplate构造方法的入参 -->
<bean name="elasticsearchTemplate"
class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
<constructor-arg ref="elasticSearchClient" />
</bean>
实例化client:
package com.xxx.xxx.elastic;
import java.net.InetAddress;
import java.util.List;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
public class TransportClientFactoryBean implements FactoryBean<TransportClient>, InitializingBean, DisposableBean{
private static final Logger logger = LoggerFactory.getLogger(TransportClientFactoryBean.class);
private String clusterName = "elasticsearch";//集群名称
private Boolean clientTransportSniff = true;//自动选举
private Boolean clientSslEnabled = false;//Elasticsearch是否开启了ssl
private TransportClient client;//客户端
private String user = "elastic";//用户名
private String pass = "changeme";//密码
private String port = "9300";//端口
private String nodes = "127.0.0.1";//ip
@Override
public void destroy() throws Exception {
try {
logger.info("Closing elasticSearch client");
if (client != null) {
client.close();
}
} catch (final Exception e) {
logger.error("Error closing ElasticSearch client: ", e);
}
}
@Override
public void afterPropertiesSet() throws Exception {
buildClient();
}
@Override
public TransportClient getObject() throws Exception {
return client;
}
@Override
public Class<?> getObjectType() {
return TransportClient.class;
}
@Override
public boolean isSingleton() {
return false;
}
protected void buildClient() throws Exception {
//创建Elasticsearch客户端
String path = Thread.currentThread().getContextClassLoader().getResource("/elastic-certificates.p12").getPath();
try {
System.setProperty("es.set.netty.runtime.available.processors", "false");
String os = System.getProperty("os.name");
if(os.toLowerCase().startsWith("win")){
path = path.substring(1);
}
Settings settings = Settings.builder().put("cluster.name", clusterName)
.put("xpack.security.transport.ssl.enabled", clientSslEnabled)
.put("xpack.security.user", user+":"+pass)
.put("xpack.security.transport.ssl.verification_mode", "certificate")
.put("xpack.security.transport.ssl.keystore.path", path)
.put("xpack.security.transport.ssl.truststore.path", path)
.put("client.transport.sniff", clientTransportSniff).build();
client = new PreBuiltXPackTransportClient(settings);
for (String node : nodes.split(",")) {
client.addTransportAddress(new TransportAddress(InetAddress.getByName(node),
Integer.valueOf(Integer.valueOf(port))));
}
//判断是否连接成功
List<DiscoveryNode> list = client.connectedNodes();
if(list!=null&&list.size()>0){
String nodeStr = "";
for(DiscoveryNode node:list){
nodeStr += ";"+node.getHostAddress();
}
logger.info("init elasticSearch client successed,connected nodes:{}", nodeStr);
}else{
logger.info("init elasticSearch client failed:connected nodes ware empty");
}
} catch (Exception e) {
logger.error("init elasticSearch client failed:", e);
}
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public Boolean getClientTransportSniff() {
return clientTransportSniff;
}
public void setClientTransportSniff(Boolean clientTransportSniff) {
this.clientTransportSniff = clientTransportSniff;
}
public Boolean getClientSslEnabled() {
return clientSslEnabled;
}
public void setClientSslEnabled(Boolean clientSslEnabled) {
this.clientSslEnabled = clientSslEnabled;
}
public TransportClient getClient() {
return client;
}
public void setClient(TransportClient client) {
this.client = client;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getNodes() {
return nodes;
}
public void setNodes(String nodes) {
this.nodes = nodes;
}
}
这步特别要注意的是设置SSL,我自己是用certificate方法创建的SSL链接,并设置了证书路径。其他方式是类似的,也是设置一个证书路径和认证方式。
接下来设置自己的Elasticsearch信息到properties文件就可以了:
esserver.cluster.name = tracklog
esserver.cluster.nodes = 172.0.0.1
esserver.cluster.port = 9300
esserver.cluster.user = elastic
esserver.cluster.pass = changeme
esserver.cluster.clientSslEnabled = true
启动项目,日志显示连接成功: