SpringBoot整合Elasticsearch详细教程

发布于:2025-04-01 ⋅ 阅读:(16) ⋅ 点赞:(0)

SpringBoot 2.6.13整合Elasticsearch详细教程

目录

  1. ​ 项目结构
  2. 添加Elasticsearch依赖
  3. 配置Elasticsearch连接
  4. 创建配置类
  5. 创建实体类
  6. 创建Repository接口
  7. 创建Service层
  8. 创建Controller层
  9. 完整示例:商品搜索系统
  10. 测试步骤
  11. 常见问题与解决方案 

项目结构

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