SpringBoot 2.6.13整合Elasticsearch详细教程
目录
- 项目结构
- 添加Elasticsearch依赖
- 配置Elasticsearch连接
- 创建配置类
- 创建实体类
- 创建Repository接口
- 创建Service层
- 创建Controller层
- 完整示例:商品搜索系统
- 测试步骤
- 常见问题与解决方案
项目结构
src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── esapp
│ │ ├── EsApplication.java # 启动类
│ │ ├── config
│ │ │ └── ElasticsearchConfig.java # ES配置类
│ │ ├── controller
│ │ │ └── BookController.java # 图书控制器
│ │ ├── model
│ │ │ └── Book.java # 图书实体类
│ │ ├── repository
│ │ │ └── BookRepository.java # 图书数据访问接口
│ │ └── service
│ │ ├── BookService.java # 图书服务接口
│ │ └── impl
│ │ └── BookServiceImpl.java # 图书服务实现类
│ └── resources
│ ├── application.yml # 配置文件
│ ├── static
│ └── templates
└── test
└── java
└── com
└── example
└── esapp
└── BookRepositoryTests.java # 测试类
添加Elasticsearch依赖
在项目的pom.xml
文件中添加相关依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.13</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
<!-- 指定Elasticsearch版本,与Spring Boot 2.6.13兼容 -->
<elasticsearch.version>7.15.2</elasticsearch.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data Elasticsearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
注意:这里使用了
elasticsearch.version
属性指定Elasticsearch的版本为7.15.2,与Spring Boot 2.6.13版本兼容。
配置Elasticsearch连接
在src/main/resources
目录下创建application.yml
文件,使用最新的配置属性:
spring:
application:
name: es-app
elasticsearch:
uris: http://localhost:9200
connection-timeout: 1s
socket-timeout: 30s
username: # 如有用户名,在此添加
password: # 如有密码,在此添加
data:
elasticsearch:
repositories:
enabled: true
server:
port: 8080
logging:
level:
org.springframework.data.elasticsearch.client.WIRE: DEBUG
org.springframework.data.elasticsearch: DEBUG
注意:这里使用了最新的配置格式,使用
spring.elasticsearch.uris
替代已废弃的属性,并分别配置了连接超时和套接字超时时间。
创建Elasticsearch配置类
在src/main/java/com/example/esapp/config
目录下创建ElasticsearchConfig.java
:
package com.example.testlogin.config;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import org.springframework.util.StringUtils;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import java.time.Duration;
@Configuration
@EnableElasticsearchRepositories(basePackages = "com.example.testlogin.repository")
public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
@Value("${spring.elasticsearch.uris}")
private String uris;
@Value("${spring.elasticsearch.connection-timeout}")
private String connectionTimeoutStr;
@Value("${spring.elasticsearch.socket-timeout}")
private String socketTimeoutStr;
@Value("${spring.elasticsearch.username:}")
private String username;
@Value("${spring.elasticsearch.password:}")
private String password;
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
// 去除http://前缀并处理多个主机情况
String[] hosts = uris.replace("http://", "").split(",");
// 使用直接的方式创建ClientConfiguration
ClientConfiguration clientConfiguration;
// 解析超时时间
Duration connectTimeout = parseTimeout(connectionTimeoutStr);
Duration socketTimeout = parseTimeout(socketTimeoutStr);
// 使用有条件的方式构建,避免类型问题
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
clientConfiguration = ClientConfiguration.builder()
.connectedTo(hosts)
.withConnectTimeout(connectTimeout)
.withSocketTimeout(socketTimeout)
.withBasicAuth(username, password)
.build();
} else {
clientConfiguration = ClientConfiguration.builder()
.connectedTo(hosts)
.withConnectTimeout(connectTimeout)
.withSocketTimeout(socketTimeout)
.build();
}
return RestClients.create(clientConfiguration).rest();
}
/**
* 创建ElasticsearchRestTemplate Bean
* 使用@Primary注解确保这个Bean被优先注入
*/
@Bean
@Primary
public ElasticsearchOperations elasticsearchOperations() {
return new ElasticsearchRestTemplate(elasticsearchClient());
}
/**
* 解析超时配置字符串为Duration对象
* @param timeout 格式如"1s", "30ms"等
* @return Duration对象
*/
private Duration parseTimeout(String timeout) {
if (timeout.endsWith("ms")) {
return Duration.ofMillis(Long.parseLong(timeout.substring(0, timeout.length() - 2)));
} else if (timeout.endsWith("s")) {
return Duration.ofSeconds(Long.parseLong(timeout.subst