SpringBoot整合easy-es

一、easy-es简介

EasyES是一款基于Elasticsearch官方提供的RestHighLevelClient开发的ORM框架,旨在简化开发流程并提高效率。 EasyES在保持RestHighLevelClient原有功能的基础上进行增强,而不做任何改变。它采用与Mybatis-Plus相似的语法,使得开发者可以无缝迁移至EasyES,无需额外学习成本。EasyES的核心理念是将简单、易用性留给用户,将复杂性留给框架,致力于成为全球最受欢迎的ElasticSearch搜索引擎开发框架。
EasyES的主要特点包括:

  • 全自动索引托管:全球开源首创的索引托管模式,无需关心索引的创建、更新及数据迁移等繁琐步骤,彻底解放开发者。
  • 屏蔽语言差异:开发者只需要会MySQL语法即可使用ES,无需学习复杂的ES语法。
  • 减少代码量:与直接使用RestHighLevelClient相比,相同的查询可以节省3-5倍的代码量。
  • 零魔法值:字段名称直接从实体中获取,无需输入字段名称字符串,提高代码可读性。
  • 降低门槛:通过EasyES,即便是只了解ES基础的初学者也可以轻松驾驭ES完成绝大多数需求的开发。
  • 无侵入:引入EasyES不会对现有工程产生影响,启动即会自动注入基本的CURD操作,性能基本无损耗。
    easy-es官网 https://www.easy-es.cn/

二、实现基于Spring Boot框架的应用程序代码

1.添加相关依赖

复制代码
<!-- 引入 Easy-ES 最新版本的依赖 -->
<dependency>
    <groupId>org.dromara.easy-es</groupId>
    <artifactId>easy-es-boot-starter</artifactId>
    <!-- 指定 Easy-ES 的版本号,确保使用的是最新稳定版本 -->
    <version>2.0.0-beta3</version>
</dependency>

<!-- 引入 Spring Boot Web 启动器,并排除内置的 Elasticsearch 依赖以避免冲突 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!-- 注释掉了版本号,这意味着 Maven 将使用项目中定义的 Spring Boot 版本 -->
    <!-- 如果没有定义,则会使用最新的可用版本 -->
    <!-- 这种方式可以在 Spring Boot 升级时自动更新依赖,但可能导致不兼容问题 -->
    <!--<version>2.7.18</version>-->
    <exclusions>
        <!-- 排除 Elasticsearch REST 高级客户端 -->
        <exclusion>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
        </exclusion>
        <!-- 排除 Elasticsearch REST 客户端 -->
        <exclusion>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
        </exclusion>
        <!-- 排除 Elasticsearch 核心库 -->
        <exclusion>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- 手动引入指定版本的 Elasticsearch REST 高级客户端 -->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <!-- 指定该客户端的版本号,以确保与其他依赖的兼容性 -->
    <version>7.14.0</version>
</dependency>

<!-- 手动引入指定版本的 Elasticsearch REST 客户端 -->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <!-- 指定该客户端的版本号,以确保与其他依赖的兼容性 -->
    <version>7.14.0</version>
</dependency>

<!-- 手动引入指定版本的 Elasticsearch 核心库 -->
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <!-- 指定核心库的版本号,以确保与其他依赖的兼容性 -->
    <version>7.14.0</version>
</dependency>

一些解释:

dependency: 定义一个项目的依赖项。每个依赖项都包含一个或多个子元素,描述该依赖的详细信息。

groupId: 指定依赖项的组织或公司名称,通常与其 Maven 仓库中的路径相对应。

artifactId: 指定依赖项的唯一标识符,通常是库或模块的名称。

version: 指定依赖项的版本号。可以是具体的版本字符串,也可以使用范围或特殊版本标识。

exclusions: 用于排除某些传递性依赖项。这样可以避免因不必要的依赖导致版本冲突。

exclusion: 在 exclusions 中定义单个被排除的依赖项。包含两个子元素:groupId 和 artifactId,用于指定要排除的依赖项。

2.添加相关配置

考虑到有的用户偏好使用YML格式进行配置,而有的用户则更喜欢使用PROPERTIES格式,为了提供便利,我同时列出了这两种类型的配置选项,以便您可以根据自己的需求和喜好进行选择。

(1)yml配置
a.基础配置
复制代码
easy-es:
  enable: true # 默认为true,若为false则认为不启用本框架
  address: 你的ip地址:9200 # 指定Elasticsearch服务的IP地址和端口,格式为IP:9200

logging:
  level:
    tracer: trace # 设置日志级别为trace,开发时可开启以打印ES全部请求信息及DSL语句
    # 注意:开启此配置后,可以将EE的print-dsl设置为false,以避免日志重复打印
b.拓展配置(可选)

不加不影响项目启动,但是为了实现性能优化,建议您根据实际需求和场景进行相应的配置调整,进行细致的配置优化

复制代码
easy-es:
  keep-alive-millis: 30000 # 心跳保持时间(毫秒)。用于确保连接在无数据传输时仍然保持活动状态,防止因长时间空闲而关闭连接。
  connect-timeout: 5000 # 连接超时设置(毫秒)。定义建立连接的最大等待时间,超过该时间则认为连接失败。
  socket-timeout: 600000 # 数据读取超时设置(毫秒)。规定读取数据时的最大等待时间,超出此时间将中断读取操作。
  request-timeout: 5000 # 请求超时设置(毫秒)。指定发送请求的最大等待时间,超过此时间则视为请求失败。
  connection-request-timeout: 5000 # 连接请求超时设置(毫秒)。定义从连接池获取连接的最大等待时间。
  max-conn-total: 100 # 最大总连接数。设置连接池中允许的最大连接数量。
  max-conn-per-route: 100 # 每个路由的最大连接数。规定针对每个目标主机可同时建立的最大连接数量。
c.全局配置(可选)

在项目启动过程中,若未明确指定相关配置,系统将自动采用预设的默认值以确保顺利运行。

复制代码
easy-es:
  schema: http # 默认为 http,可选值为 https(不使用 SSL)。配置为 https 时,使用 HTTPS 协议。
  banner: true # 默认为 true,是否打印启动横幅。若不需要打印,设置为 false。
  global-config:
    i-kun-mode: false # 是否开启小黑子模式,默认为关闭。开启后日志会更加有趣,仅供娱乐用途。
    process-index-mode: manual # 索引处理模式。可选值:smoothly(平滑模式)、not_smoothly(非平滑模式)和 manual(手动模式),默认开启手动模式。
    print-dsl: true # 是否在控制台打印通过该框架生成的 DSL 语句。默认为 true,建议在测试稳定后生产环境中关闭以提高性能。
    distributed: false # 当前项目是否为分布式项目。默认为 true。在非手动托管索引模式下,分布式项目会获取分布式锁,非分布式项目使用 synchronized 锁。
    reindexTimeOutHours: 72 # 重建索引的超时时间,单位为小时。默认值为 72 小时,根据 ES 中存储的数据量可调整。
    async-process-index-blocking: true # 异步处理索引是否阻塞主线程。默认阻塞。当数据量过大时,可调整为非阻塞,以加快项目启动速度。
    active-release-index-max-retry: 4320 # 在分布式环境下,平滑模式下当前客户端激活最新索引的最大重试次数。若数据量过大,重建索引数据迁移时间超过 72 小时,可增大此参数。
    active-release-index-fixed-delay: 60 # 在分布式环境下,平滑模式下当前客户端激活最新索引的重试时间间隔。若希望最终一致性时效性更高,可减小此值,但会牺牲一些性能。
    
    db-config:
      map-underscore-to-camel-case: false # 是否开启下划线转驼峰命名,默认为 false。
      index-prefix: daily_ # 索引前缀,用于区分环境。默认为空,作用与 MP 的 tablePrefix 相同。
      id-type: customize # ID 生成策略。可选值为 customize(自定义),用户可以自行生成 ID(例如取自 MySQL 的数据 ID)。默认使用 ES 自动生成 ID。
      field-strategy: not_empty # 字段更新策略,默认为 not_null(不为空)。
      enable-track-total-hits: true # 是否开启总数据匹配追踪,默认为开启。若不开启,将无法获取数据总条数。查询数量突破 1 万条时,需要同步调整 @IndexName 注解中的 maxResultWindow。
      refresh-policy: immediate # 数据刷新策略。默认为不刷新。若对数据时效性要求较高,可调整为 immediate,但会有性能损耗,也可选择 wait_until 作为折中方案。
      batch-update-threshold: 10000 # 批量更新接口的阈值,默认值为 1 万。突破此值时需同步调整 enable-track-total-hits=true 和 @IndexName.maxResultWindow > 1w,并重建索引。
      smartAddKeywordSuffix: true # 是否智能为字段添加 .keyword 后缀。默认开启,会根据当前字段的索引类型及查询类型自动判断是否需要拼接 .keyword 后缀。
多数据源(可选)
复制代码
easy-es:
  dynamic:
    datasource:
      ds1:
        address: 你的ip地址:9200 # 数据源1的连接地址
        # username: '可省略,如果没有用户名'
        # password: '可省略,如果没有密码'
      ds2:
        address: 你的ip地址:9200 # 数据源2的连接地址
        # username: '可省略,如果没有用户名'
        # password: '可省略,如果没有密码'
      # 其他数据源配置...
(2)properties配置
a.基础配置
复制代码
# Easy-ES 配置
easy-es.enable=true # 启用框架,默认为true,设置为false则禁用此框架
easy-es.address=你的ip地址:9200 # 设置Elasticsearch的连接地址

# 日志配置
logging.level.tracer=trace # 设置日志级别为trace,开发时可开启,以打印所有Elasticsearch请求信息及DSL语句
# 注意:开启此配置后,可将EE的print-dsl设置为false以避免重复打印
b.拓展配置(可选)

不加不影响项目启动,但是为了实现性能优化,建议您根据实际需求和场景进行相应的配置调整,进行细致的配置优化

复制代码
# Easy-ES 配置

easy-es.keep-alive-millis=30000 # 心跳策略时间,单位:毫秒(ms)。设置保持连接活动的时间,以防长时间无数据传输导致连接关闭。

easy-es.connect-timeout=5000 # 连接超时时间,单位:毫秒(ms)。设置建立连接时的超时时间。

easy-es.socket-timeout=600000 # 通信超时时间,单位:毫秒(ms)。设置读取数据的超时时间,超过此时间将中断读取。

easy-es.request-timeout=5000 # 请求超时时间,单位:毫秒(ms)。设置发送请求的超时时间,超出该时间将认为请求失败。

easy-es.connection-request-timeout=5000 # 连接请求超时时间,单位:毫秒(ms)。设置从连接池中获取连接的超时时间。

easy-es.max-conn-total=100 # 最大连接数,单位:个。设置连接池中最大允许的连接总数。

easy-es.max-conn-per-route=100 # 最大连接路由数,单位:个。设置每个路由(目标主机)的最大连接数。
c.全局配置(可选)

在项目启动过程中,若未明确指定相关配置,系统将自动采用预设的默认值以确保顺利运行。

复制代码
# ES连接协议,默认为http,可省略;支持https免SSL方式,配置为https即可
easy.es.schema=http

# 是否打印banner,默认为true;不想打印时可设置为false
easy.es.banner=true

# 是否开启小黑子模式,默认为关闭;开启后日志将更有趣,仅供娱乐用途
easy.es.global-config.i-kun-mode=false

# 索引处理模式:
# smoothly: 平滑模式
# not_smoothly: 非平滑模式
# manual: 手动模式(默认)
easy.es.global-config.process-index-mode=manual

# 是否在控制台打印框架生成的DSL语句,默认开启;生产环境建议关闭以提升性能
easy.es.global-config.print-dsl=true

# 当前项目是否为分布式项目,默认为true;非分布式项目只需使用synchronized锁
easy.es.global-config.distributed=false

# 重建索引超时时间,单位为小时,默认为72小时;可根据ES中存储的数据量调整
easy.es.global-config.reindexTimeOutHours=72

# 异步处理索引是否阻塞主线程,默认阻塞;数据量过大时可设置为非阻塞,加快项目启动
easy.es.global-config.async-process-index-blocking=true

# 分布式环境下,平滑模式下当前客户端激活最新索引的最大重试次数
# 数据量过大时,重建索引数据迁移时间超过72小时可调大此参数
easy.es.global-config.active-release-index-max-retry=4320

# 分布式环境下,平滑模式下当前客户端激活最新索引的重试时间间隔
# 若需要更高的一致性时效性可调小此值,但会影响性能
easy.es.global-config.active-release-index-fixed-delay=60

# 是否开启下划线转驼峰命名,默认为false;如果需要可设置为true
easy.es.global-config.db-config.map-underscore-to-camel-case=false

# 索引前缀,用于区分不同环境,默认为空;用法与MP的tablePrefix相同
easy.es.global-config.db-config.index-prefix=daily_

# ID生成策略:
# customize: 自定义,由用户生成ID(例如:取MySQL中的数据ID)
# 默认情况下,ID由ES自动生成
easy.es.global-config.db-config.id-type=customize

# 字段更新策略,默认为not_null;表示只更新非空字段
easy.es.global-config.db-config.field-strategy=not_empty

# 是否开启总数追踪,默认开启;若不开启,则无法获取数据总条数,但其他功能不受影响
# 查询数量超过1万时,需要调整@IndexName注解中的maxResultWindow大于1万,并重建索引
easy.es.global-config.db-config.enable-track-total-hits=true

# 数据刷新策略,默认为不刷新;对数据时效性要求高时可设置为immediate,但性能损耗较高,也可选择折中的wait_until
easy.es.global-config.db-config.refresh-policy=immediate

# 批量更新接口的阈值,默认值为1万;突破此值需同步调整enable-track-total-hits=true,@IndexName.maxResultWindow > 1w,并重建索引
easy.es.global-config.db-config.batch-update-threshold=10000

# 是否智能为字段添加.keyword后缀,默认开启;根据字段的索引类型及查询类型自动判断是否需要拼接.keyword后缀
easy.es.global-config.db-config.smartAddKeywordSuffix=true
多数据源(可选)
复制代码
# 动态数据源配置

# 数据源1的连接地址,请替换为实际的IP地址和端口
easy.es.dynamic.datasource.ds1.address=你的ip地址:9200
# 若数据源1需要用户名,可以在此填写;若无用户名可去掉此行
# easy.es.dynamic.datasource.ds1.username=
# 若数据源1需要密码,可以在此填写;若无密码可去掉此行
# easy.es.dynamic.datasource.ds1.password=

# 可以继续添加更多的数据源,示例如下:
# 数据源2的连接地址,请替换为实际的IP地址和端口
easy.es.dynamic.datasource.ds2.address=你的ip地址:9200
# 若数据源2需要用户名,可以在此填写;若无用户名可去掉此行
# easy.es.dynamic.datasource.ds2.username=
# 若数据源2需要密码,可以在此填写;若无密码可去掉此行
# easy.es.dynamic.datasource.ds2.password=

三、实现基于Spring Boot框架的应用程序代码(测试)

1.创建一个实体

复制代码
import lombok.Data;
import org.dromara.easyes.annotation.HighLight;
import org.dromara.easyes.annotation.IndexField;
import org.dromara.easyes.annotation.IndexId;
import org.dromara.easyes.annotation.IndexName;
import org.dromara.easyes.annotation.rely.Analyzer;
import org.dromara.easyes.annotation.rely.FieldType;
import org.dromara.easyes.annotation.rely.IdType;

import java.math.BigDecimal;
import java.util.Date;



@Data
// 指定 Elasticsearch 索引名称及其分片数
@IndexName(value = "user_es", shardsNum = 3)
public class User {

    /**
     * 用户唯一标识符
     * 使用自定义 ID 类型
     */
    @IndexId(type = IdType.CUSTOMIZE)
    private Integer id;

    /**
     * 用户姓名
     * 字段类型为 TEXT,采用 IK 最大词元分词器进行索引与搜索
     * 在搜索结果中匹配的内容将被高亮显示
     */
    @IndexField(value = "userName", fieldType = FieldType.TEXT, analyzer = Analyzer.IK_MAX_WORD, searchAnalyzer = Analyzer.IK_MAX_WORD)
    @HighLight(preTag = "<span style="color:red">", postTag = "</span>")
    private String name;

    /**
     * 用户年龄
     * 字段类型为 INTEGER
     */
    @IndexField(fieldType = FieldType.INTEGER)
    private Integer age;

    /**
     * 用户薪资
     * 字段类型为 DOUBLE
     */
    @IndexField(fieldType = FieldType.DOUBLE)
    private BigDecimal salary;

    /**
     * 用户出生日期
     * 字段类型为 DATE
     */
    @IndexField(fieldType = FieldType.DATE)
    private Date birthday;
}

注释详解:

@IndexName:

value = "user_es": 指定索引名称为 user_es。

shardsNum = 3: 设置分片数量为 3。

replicasNum = 1: 设置副本数量为 1。

@IndexId:

type = IdType.CUSTOMIZE: 指定 ID 类型为自定义。
@IndexField:

value = "userName": 指定字段在 Elasticsearch 中的名称为 userName。

fieldType = FieldType.TEXT: 指定字段类型为 TEXT。

analyzer = Analyzer.IK_MAX_WORD: 指定索引时使用的分词器为 IK_MAX_WORD。

searchAnalyzer = Analyzer.IK_MAX_WORD: 指定搜索时使用的分词器为 IK_MAX_WORD。

@HighLight:

preTag = "": 高亮部分前缀标签。

postTag = "": 高亮部分后缀标签。

2.相关方法

<1>.基本 CRUD 操作方法
(1)insert(T entity)
a.描述:

插入一条记录。

b.参数:

T entity - 要插入的实体对象。

c.返回值:

boolean - 插入是否成功。

(2)insertBatch(List entities)
a.描述:

批量插入记录。

b.参数:

List entities - 要插入的实体对象列表。

c.返回值:

boolean - 插入是否成功。

(3)deleteById(Object id)
a.描述:

根据 ID 删除记录。

b.参数:

Object id - 要删除的记录的 ID。

c.返回值:

boolean - 删除是否成功。

(4)deleteBatchIds(Listids)
a.描述:

批量删除记录。

b.参数:

Listids - 要删除的记录的 ID 列表。

c.返回值:

boolean - 删除是否成功。

(5)updateById(T entity)
a.描述:

根据 ID 更新记录。

b.参数:

T entity - 要更新的实体对象。

c.返回值:

boolean - 更新是否成功。

(6)update(T entity, Wrapper wrapper)
a.描述:

根据条件更新记录。

b.参数:

T entity - 要更新的实体对象。

Wrapper wrapper - 更新条件。

c.返回值:

boolean - 更新是否成功。

(7)selectById(Object id)
a.描述:

根据 ID 查询记录。

b.参数:

Object id - 要查询的记录的 ID。

c.返回值:

T - 查询到的实体对象。

(8)selectList(Wrapper queryWrapper)
a.描述:

根据条件查询记录列表。

b.参数:

Wrapper queryWrapper - 查询条件。

c.返回值:

List - 查询到的实体对象列表。

<2>. 批量操作
(1)insertOrUpdate(T entity)
a.描述:

插入或更新记录。如果记录存在则更新,否则插入。

b.参数:

T entity - 要插入或更新的实体对象。

c.返回值:

boolean - 操作是否成功。

(2)insertOrUpdateBatch(List entities)
a.描述:

批量插入或更新记录。如果记录存在则更新,否则插入。

b.参数:

List entities - 要插入或更新的实体对象列表。

c.返回值:

boolean - 操作是否成功。

<3>. 查询操作
(1)selectOne(Wrapper queryWrapper)
a.描述:

根据条件查询单条记录。

b.参数:

Wrapper queryWrapper - 查询条件。

c.返回值:

T - 查询到的实体对象。

(2)selectCount(Wrapper queryWrapper)
a.描述:

根据条件查询记录总数。

b.参数:

Wrapper queryWrapper - 查询条件。

c.返回值:

long - 记录总数。

(3)selectPage(Page page, Wrapper queryWrapper)
a.描述:

分页查询记录。

b.参数:

Page page - 分页对象。

Wrapper queryWrapper - 查询条件。

c.返回值:

IPage - 分页结果。

(4)selectMaps(Wrapper queryWrapper)
a.描述:

根据条件查询记录列表,返回 Map 形式的列表。

b.参数:

Wrapper queryWrapper - 查询条件。

c.返回值:

List> - 查询到的记录列表。

(5)selectObjs(Wrapper queryWrapper)
a.描述:

根据条件查询记录列表,返回单个字段的值列表。

b.参数:

Wrapper queryWrapper - 查询条件。

c.返回值:

List - 查询到的记录列表。

<4>. 其他方法
(1)exists(Wrapper queryWrapper)
a.描述:

根据条件判断记录是否存在。

b.参数:

Wrapper queryWrapper - 查询条件。

c.返回值:

boolean - 记录是否存在。

(2)getSource(Wrapper queryWrapper)
a.描述:

获取查询条件对应的 DSL 语句。

b.参数:

Wrapper queryWrapper - 查询条件。

c.返回值:

String - DSL 语句。

3.代码示例

(1)mapper层(持久层)

建议:Easy-Es的Mapper和MyBatis-Plus分开存放 一个是查数据库的,一个是查es的

复制代码
import org.dromara.easyes.core.core.BaseEsMapper;

/**
 * 用户 Elasticsearch 数据访问接口
 * 
 * 该接口继承自 BaseEsMapper,专门用于处理 User 实体类的 Elasticsearch 操作。
 * 通过此接口,可以实现对用户数据的增删改查等操作。
 * 
 * @see BaseEsMapper
 * @see User
 */
public interface UserESMapper extends BaseEsMapper<User> {
    // 此接口可以在未来添加自定义的用户相关查询方法
}

注意:本接口仅用于执行ES(Elasticsearch)相关操作,不涉及数据库操作,请避免功能冲突。

(2)业务逻辑层(Service)
复制代码
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;

import java.util.List;

/**
 * 用户服务接口
 *
 * 提供用户相关的操作,包括插入、查询、更新和删除用户信息。
 * 本接口定义了一系列方法,用于与用户数据进行交互。
 * 具体实现应支持ElasticSearch存储和查询。
 *
 * @author [您的名字]
 * @version 1.0
 * @since [日期]
 */
public interface UserEsService {

    /**
     * 插入用户信息
     *
     * @param user 用户对象,包含要插入的用户信息
     * @return 操作影响的行数,通常为1表示成功,0表示失败
     */
    Integer insertUser(User user);

    /**
     * 根据用户ID查询用户信息
     *
     * @param id 用户ID,唯一标识一个用户
     * @return 用户对象,查询成功时返回用户信息,未找到则返回null
     */
    User getUserById(Integer id);

    /**
     * 查询满足条件的用户列表
     *
     * @param queryWrapper 查询条件封装,包含查询所需的所有条件
     * @return 用户列表,符合条件的用户集合,可能为空
     */
    List<User> getUserList(LambdaEsQueryWrapper<User> queryWrapper);

    /**
     * 更新指定ID的用户信息
     *
     * @param user 用户对象,需包含ID和更新后的用户信息
     * @return 操作影响的行数,通常为1表示成功,0表示失败
     */
    Integer updateUserById(User user);

    /**
     * 删除指定ID的用户信息
     *
     * @param id 用户ID,唯一标识要删除的用户
     * @return 操作影响的行数,通常为1表示成功,0表示失败
     */
    Integer deleteUserById(Integer id);

    /**
     * 分页查询用户信息
     *
     * @param queryWrapper 查询条件封装,包含分页信息和其他查询条件
     * @return 用户列表,符合条件的用户集合,可能为空
     */
    List<User> getUserListWithPage(LambdaEsQueryWrapper<User> queryWrapper);
}
(3)实现层(ServiceImpl)
复制代码
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 用户服务实现类
 *
 * 实现了 UserEsService 接口,提供与用户相关的操作,包括插入、查询、更新和删除用户信息。
 * 通过 UserESMapper 与 ElasticSearch 进行交互。
 *
 * @author [您的名字]
 * @version 1.0
 * @since [日期]
 */
@Service
public class UserEsServiceImpl implements UserEsService {

    @Autowired
    private UserESMapper userEsMapper;

    /**
     * 插入用户信息到数据库
     *
     * @param user 用户对象,包含要插入的用户信息
     * @return 操作影响的行数,通常为1表示成功,0表示失败
     */
    @Override
    public Integer insertUser(User user) {
        // 插入用户信息到数据库
        return userEsMapper.insert(user);
    }

    /**
     * 根据用户ID查询用户信息
     *
     * @param id 用户ID,唯一标识一个用户
     * @return 用户对象,查询成功时返回用户信息,未找到则返回null
     */
    @Override
    public User getUserById(Integer id) {
        // 根据用户ID查询用户信息
        return userEsMapper.selectById(id);
    }

    /**
     * 查询满足条件的用户列表
     *
     * @param queryWrapper 查询条件封装,包含查询所需的所有条件
     * @return 用户列表,符合条件的用户集合,可能为空
     */
    @Override
    public List<User> getUserList(LambdaEsQueryWrapper<User> queryWrapper) {
        // 查询满足条件的用户列表
        return userEsMapper.selectList(queryWrapper);
    }

    /**
     * 更新指定ID的用户信息
     *
     * @param user 用户对象,需包含ID和更新后的用户信息
     * @return 操作影响的行数,通常为1表示成功,0表示失败
     */
    @Override
    public Integer updateUserById(User user) {
        // 更新指定ID的用户信息
        return userEsMapper.updateById(user);
    }

    /**
     * 删除指定ID的用户信息
     *
     * @param id 用户ID,唯一标识要删除的用户
     * @return 操作影响的行数,通常为1表示成功,0表示失败
     */
    @Override
    public Integer deleteUserById(Integer id) {
        // 删除指定ID的用户信息
        return userEsMapper.deleteById(id);
    }

    /**
     * 分页查询用户信息
     *
     * @param queryWrapper 查询条件封装,包含分页信息和其他查询条件
     * @return 用户列表,符合条件的用户集合,可能为空
     */
    @Override
    public List<User> getUserListWithPage(LambdaEsQueryWrapper<User> queryWrapper) {
        // 分页查询用户信息
        return userEsMapper.selectList(queryWrapper);
    }
}
(4)表现层(Controller)
复制代码
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;


/**
 * 用户控制器
 *
 * 提供与用户相关的 RESTful API 接口,包括插入、查询、更新和删除用户信息。
 * 所有请求均以 /user-es 为前缀。
 *
 * @author [您的名字]
 * @version 1.0
 * @since [日期]
 */
@RestController
@RequestMapping("/user-es")
public class UserEsController {

    @Autowired
    private UserEsService userService;

    /**
     * 插入用户信息
     *
     * @param user 用户对象,包含要插入的用户信息
     * @return 插入操作影响的行数,通常为1表示成功,0表示失败
     */
    @PostMapping
    public Integer insertUser(@RequestBody User user) {
        // 插入用户信息
        return userService.insertUser(user);
    }

    /**
     * 根据用户ID查询用户信息
     *
     * @param id 用户ID,唯一标识一个用户
     * @return 用户对象,查询成功时返回用户信息,未找到则返回null
     */
    @GetMapping("/{id}")
    public User getUserById(@PathVariable Integer id) {
        // 根据用户ID查询用户信息
        return userService.getUserById(id);
    }

    /**
     * 查询满足条件的用户列表
     *
     * @param age 可选参数,查询指定年龄的用户
     * @return 用户列表,符合条件的用户集合,可能为空
     */
    @GetMapping
    public List<User> getUserList(@RequestParam(required = false) Integer age) {
        // 查询满足条件的用户列表
        LambdaEsQueryWrapper<User> queryWrapper = new LambdaEsQueryWrapper<>();
        if (age != null) {
            queryWrapper.eq(User::getAge, age); // 添加等于年龄的查询条件
        }
        return userService.getUserList(queryWrapper);
    }

    /**
     * 更新指定ID的用户信息
     *
     * @param user 用户对象,需包含ID和更新后的用户信息
     * @return 更新操作影响的行数,通常为1表示成功,0表示失败
     */
    @PutMapping
    public Integer updateUserById(@RequestBody User user) {
        // 更新指定ID的用户信息
        return userService.updateUserById(user);
    }

    /**
     * 删除指定ID的用户信息
     *
     * @param id 用户ID,唯一标识要删除的用户
     * @return 删除操作影响的行数,通常为1表示成功,0表示失败
     */
    @DeleteMapping("/{id}")
    public Integer deleteUserById(@PathVariable Integer id) {
        // 删除指定ID的用户信息
        return userService.deleteUserById(id);
    }

    /**
     * 分页查询用户信息
     *
     * @param from 分页起始位置
     * @param size 每页大小
     * @return 用户列表,符合条件的用户集合,可能为空
     */
    @GetMapping("/page")
    public List<User> getUserListWithPage(@RequestParam(defaultValue = "0") int from,
                                          @RequestParam(defaultValue = "10") int size) {
        // 分页查询用户信息
        LambdaEsQueryWrapper<User> queryWrapper = new LambdaEsQueryWrapper<>();
        queryWrapper.from(from).size(size); // 设置分页起始位置和大小
        return userService.getUserListWithPage(queryWrapper);
    }
}

4.遭遇的技术难题与挑战

(1)缺少一些jackson的相关依赖

如果发生以下报错可能是因为缺少一些jackson的相关依赖

报错信息

org.springfranework.beans. factory.BeanCreationException Ceae brekpont : Error creating bean with nane 'reguestHappingHandlerAdapter' defined in class path resource org/springfranework/boot/autoconfigure/neb/servlet/NebHvckutoConfigurationsEnablelebHvcConfiguration.

翻译

org.springfranework.beans。工厂。在类路径资源org/springfranework/boot/autoconfigure/neb/servlet/NebHvckutoConfigurationsEnablelebHvcConfiguration中定义名称为'reguestHappingHandlerAdapter'的bean创建错误。

报错全部信息
复制代码
org.springfranework.beans. factory.BeanCreationException Ceae brekpont : Error creating bean with nane 'reguestHappingHandlerAdapter' defined in class path resource [org/springfranework/boot/autoconfigure/neb/servlet/NebHvckutoConfigurationsEnablelebHvcConfiguration.
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) [spring-beans-5.3.31.jar:5.3.31)lat org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:633) [spring-beans-5.3.31.jar:5.3.31at org.
springframework beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) [spring-beans-5.3.31.jar:5.3.31]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) [spring-beans-5.3.31.jar:5.3.31]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) 
[spring-beans-5.3.31.jar:5.3.31 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) [spring-beans-5.3.31.jar:5.3.31 at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$e(AbstractBeanFactory.java:335) [spring-beans-5.3.31.jar:5.3.31]at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) 
[spring-beans-5.3.31.jar:5.3.31]at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.lava:333) -[spring-beans-5.3.31.jar:5.3.31] lat org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) [spring-beans-5.3.31.jar:5.3.31]at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultlistableBeanFactory.java:955) [spring-beans-5.3.31.jar:5.3.31]at 
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:929) [spring-context-5.3.31.jar:5.3.31)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:591) [spring-context-5.3.31.jar:5.3.31]at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) [spring-boot-2.7.18.jar:2.7.18)at 
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) [spring-boot-2.7.18.jar:2.7.18]lat org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) [spring-boot-2.7.18.jar:2.7.18]at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-2.7.18.jar:2.7.18]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) [spring-boot-2.7.18.jar:2.7.18]at 
org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) [spring-boot-2.7.18.jar:2.7.18]lat com.gjc.EasyEsApplication.main(EasyEsApplication.java:13) [classes/:na]CSDN @Love-Sto
解决方法:根据要加入相关依赖
复制代码
<dependencies>
    <!-- Jackson 数据绑定核心库,用于将 Java 对象与 JSON 数据进行转换 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.13.3</version> <!-- 请使用最新版本 -->
    </dependency>

    <!-- Jackson 核心库,提供基本的 JSON 处理功能 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.13.3</version> <!-- 请使用最新版本 -->
    </dependency>

    <!-- Jackson 注解库,提供用于序列化和反序列化的注解 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.13.3</version> <!-- 请使用最新版本 -->
    </dependency>
</dependencies>

注: 会报错的原因在于Spring Boot的自动配置机制依赖于这些库来处理JSON数据的序列化和反序列化。具体来说,jackson-databind、jackson-core 和 jackson-annotations 是Jackson库的核心组件,Spring Boot使用它们来处理HTTP请求和响应中的JSON数据。

以下是对每个依赖项的详细解释:
a. jackson-databind
作用:

提供数据绑定功能,即将JSON数据转换为Java对象(反序列化)和将Java对象转换为JSON数据(序列化)。

重要性:

这是Jackson库的核心部分,Spring Boot的MappingJackson2HttpMessageConverter依赖于它来处理HTTP请求和响应中的JSON数据。

b. jackson-core
作用:

提供底层的流式API,用于高效地读取和写入JSON数据。

重要性:

jackson-databind依赖于jackson-core来实现其数据绑定功能。没有jackson-core,jackson-databind无法正常工作。

c. jackson-annotations
作用:

提供注解支持,用于控制JSON数据的序列化和反序列化行为。

重要性:

虽然不是必需的,但这些注解(如@JsonProperty、@JsonDeserialize等)在处理复杂的JSON数据结构时非常有用。Spring Boot的一些自动配置功能也依赖于这些注解。

为什么缺少这些依赖会报错?
a.MappingJackson2HttpMessageConverter 依赖:

Spring Boot的WebMvcAutoConfiguration会自动配置一个RequestMappingHandlerAdapter,该适配器需要MappingJackson2HttpMessageConverter来处理JSON数据。

MappingJackson2HttpMessageConverter依赖于jackson-databind来实现JSON的序列化和反序列化。

b.jackson-databind 依赖:

如果没有jackson-databind,MappingJackson2HttpMessageConverter无法实例化,从而导致RequestMappingHandlerAdapter的初始化失败。

c.jackson-core 依赖:

jackson-databind依赖于jackson-core来实现底层的JSON读写操作。如果没有jackson-core,jackson-databind也无法正常工作。

d.jackson-annotations 依赖:

虽然jackson-annotations不是必须的,但在某些情况下,Spring Boot的自动配置可能会使用这些注解来优化JSON处理。缺少这些注解可能会导致一些高级功能无法正常使用。

(2)easy-es当前支持的SpringBoot版本

easy-es 是一个基于Elasticsearch的Java EE开发框架,它不直接支持Spring Boot 3.0及以上版本,因为它可能依赖于Spring Boot 2.x系列的特定API或者功能。

如果你需要在Spring Boot 3.0以上版本使用类似easy-es的功能,你可以寻找是否有支持Spring Boot 3.x的版本,或者等待easy-es更新以支持新版本。

如果你不得不在Spring Boot 3.0以上版本使用类似easy-es的功能,你可以考虑以下两种方案:

  1. 查看easy-es的最新版本是否支持Spring Boot 3.x,如果有,则升级到支持的版本。
  2. 如果easy-es没有发布支持Spring Boot 3.x的新版本,你可以尝试自己对现有版本进行修改,使其兼容Spring Boot 3.x,但这可能需要较多的工作和测试。

在进行任何升级或修改之前,请确保检查easy-es的官方文档和发布说明,以获取有关兼容性和任何重大更改的信息。

注:本文开头提供了easy-es的官网

目前的错误信息就是这些,未来遇到新的问题将会逐步记录和补充。

相关推荐
豌豆花下猫1 小时前
Python 潮流周刊#118:Python 异步为何不够流行?(摘要)
后端·python·ai
尚学教辅学习资料1 小时前
Ruoyi-vue-plus-5.x第五篇Spring框架核心技术:5.1 Spring Boot自动配置
vue.js·spring boot·spring
晚安里2 小时前
Spring 框架(IoC、AOP、Spring Boot) 的必会知识点汇总
java·spring boot·spring
秋难降2 小时前
SQL 索引突然 “罢工”?快来看看为什么
数据库·后端·sql
上官浩仁2 小时前
springboot ioc 控制反转入门与实战
java·spring boot·spring
Access开发易登软件3 小时前
Access开发导出PDF的N种姿势,你get了吗?
后端·低代码·pdf·excel·vba·access·access开发
叫我阿柒啊3 小时前
从Java全栈到前端框架:一位程序员的实战之路
java·spring boot·微服务·消息队列·vue3·前端开发·后端开发
中国胖子风清扬3 小时前
Rust 序列化技术全解析:从基础到实战
开发语言·c++·spring boot·vscode·后端·中间件·rust
bobz9654 小时前
分析 docker.service 和 docker.socket 这两个服务各自的作用
后端
野犬寒鸦4 小时前
力扣hot100:旋转图像(48)(详细图解以及核心思路剖析)
java·数据结构·后端·算法·leetcode