导读:本期聚焦于小菜鸟创作的《Spring Boot 如何整合 Spring Data Solr 快速实现搜索功能?》,敬请观看详情。构建搜索模块时,如果直接从SolrJ客户端开始写,连接管理、查询构造和结果映射会带来不少重复代码。Spring Boot生态对Solr提供了自动化配置支持,配合Spring Data Solr的Repository抽象,可以把搜索功能像普通数据库操作一样用接口方法完成。本文基于Maven工程演示完整整合过程,先创建Solr核心并配置schema,接着引入starter依赖并设置连接参数,然后定义带SolrDocument注解的文档实体和Repository接口,再结合SolrTemplate实现分页查询、高亮显示和过滤条件。文中还会说明中文分词器的选择以及实际调用时常见的字段类型不匹配问题。代码覆盖依赖、配置、实体、服务层和接口测试,读者可以直接套用到自己的项目里快速搭建一个可用的全文搜索服务。

全文搜索在商品列表、文章检索和日志分析等场景中非常常见。Solr 基于 Apache Lucene 构建,提供了独立的搜索服务、分布式索引和丰富的查询语法;而 Spring Data Solr 则是 Spring 生态中专门用来简化 Solr 操作的模块。传统做法里直接使用 SolrJ 客户端虽然可行,但需要手动管理连接、构建 SolrInputDocument、解析查询结果,样板代码量大。Spring Boot 的自动配置加上 Spring Data Solr 的 Repository 抽象,能把这些繁琐步骤尽量隐藏起来,让开发者更专注于搜索逻辑本身。

Spring Boot 如何整合 Spring Data Solr 快速实现搜索功能?

一、搭建 Solr 服务并准备核心配置

在开始写 Spring Boot 代码之前,需要先有一个可用的 Solr 实例。可以选择下载 Solr 二进制包本地启动,也可以通过 Docker 一条命令运行。为了快速验证,Docker 方式比较省事。假设使用 Solr 8 或 9 版本,启动容器后进入管理界面创建 core。core 相当于数据库中的一张表,用来存储一类文档的索引。创建 core 时可以选择默认配置,但更好的做法是根据业务字段手动调整 schema。

Solr 的 schema 定义了字段名称、字段类型以及是否索引、是否存储等属性。例如商品搜索通常需要 id、title、description、price、createTime 这几个字段。其中 title 和 description 需要做全文匹配,可以使用 Solr 自带的 text_general 类型;如果涉及中文,建议替换为 SmartChineseAnalyzer 或 IK Analyzer 对应的字段类型。下面给出一个 managed-schema 中的核心字段示例。

<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false"/>
<field name="title" type="text_general" indexed="true" stored="true"/>
<field name="description" type="text_general" indexed="true" stored="true"/>
<field name="price" type="pdouble" indexed="true" stored="true"/>
<field name="createTime" type="pdate" indexed="true" stored="true"/>
<uniqueKey>id</uniqueKey>

配置完成后重启 Solr 或重新加载 core,使 schema 生效。如果使用 SolrCloud 模式,schema 变更可以通过 API 上传,但本地单机调试直接改文件更直观。此时可以在管理界面的 Query 页面用 q=*:* 测试,应该能正常返回空结果集,说明 core 已经就绪。

二、配置 Spring Boot 工程与依赖

创建 Spring Boot 项目时,选择 Maven 或 Gradle 均可。核心依赖是 spring-boot-starter-data-solr,它会传递引入 Spring Data Solr 和 SolrJ。如果使用 Spring Boot 2.x 版本,可以直接添加该 starter;Spring Boot 3.x 需要确认依赖名称是否仍然可用,因为部分模块可能会拆分。除了 Solr 依赖,还需要一个 Web 依赖来暴露接口。

Maven 的 pom.xml 关键依赖如下。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

接下来在 application.yml 中配置 Solr 连接地址。单机模式下只需要指定 solr.host 即可,格式为 http://localhost:8983/solr。如果 Solr 开启认证,则需要配置用户名和密码。示例配置如下。

spring:
  data:
    solr:
      host: http://localhost:8983/solr
      repositories:
        enabled: true

这里 spring.data.solr.host 是 Spring Data Solr 自动配置读取的关键属性。如果使用 SolrCloud 集群,还需要提供 zookeeper 地址列表。配置完成后 Spring Boot 会自动创建 SolrClient 和 SolrTemplate 实例,后续可以直接注入使用。

三、定义文档实体与 Repository

Spring Data Solr 支持通过注解将 Java 对象映射为 Solr 文档。实体类需要用 SolrDocument 标注,并指定 collection 或 core 名称。字段通过 @Id、@Indexed、@Field 等注解来描述。@Id 用来标记主键,对应 Solr 的 uniqueKey;@Indexed 可以指定字段名,如果 Java 属性名与 Solr 字段名不一致时使用 name 参数。

import org.springframework.data.annotation.Id;
import org.springframework.data.solr.core.mapping.Indexed;
import org.springframework.data.solr.core.mapping.SolrDocument;

@SolrDocument(collection = "product")
public class Product {
    @Id
    @Indexed(name = "id", type = "string")
    private String id;

    @Indexed(name = "title", type = "text_general")
    private String title;

    @Indexed(name = "description", type = "text_general")
    private String description;

    @Indexed(name = "price", type = "pdouble")
    private Double price;

    @Indexed(name = "createTime", type = "pdate")
    private String createTime;

    // getter/setter 省略
}

如果需要更灵活的字段映射,可以使用 @Field 注解,但通常情况下 @Indexed 已经足够。实体类中的 getter 和 setter 必须完整,否则框架反射赋值时会失败。还要注意日期类型最好使用 String 或 java.util.Date,并保证格式与 Solr 字段类型匹配,避免索引写入时报类型转换错误。

定义好实体后,可以创建一个继承 SolrCrudRepository 的接口。它提供 save、findById、delete、count 等基础方法,还可以声明自定义方法名,由框架自动解析成 Solr 查询。例如按标题搜索可以写成 findByTitleContaining(String keyword)。

import org.springframework.data.solr.repository.SolrCrudRepository;
import java.util.List;

public interface ProductRepository extends SolrCrudRepository<Product, String> {
    List<Product> findByTitleContaining(String keyword);
    List<Product> findByPriceBetween(Double min, Double max);
}

Repository 的查询方法命名规则与 Spring Data JPA 类似,支持 Containing、And、Or、Between 等关键字。不过 Solr 的查询能力更偏向全文检索,单纯依赖方法名解析只能覆盖简单场景。复杂查询还是需要借助 SolrTemplate 或 Query 对象来实现。

四、使用 SolrTemplate 实现分页与高亮

SolrTemplate 是 Spring Data Solr 提供的核心操作类,封装了 SolrClient 的常见操作。通过它可以直接构造 Query 对象,实现分页、过滤、排序、高亮等功能。相比 Repository 方法,SolrTemplate 更加灵活,适合真实业务中的搜索条件拼接。

先构造一个 SimpleQuery,设置查询条件。SimpleQuery 支持 Criteria 构建条件,例如查询 title 或 description 中包含关键字,并限制价格范围。分页通过 setOffset 和 setRows 控制,排序使用 addSort。高亮需要单独构造 HighlightOptions,并设置高亮字段和前后缀。

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.*;
import org.springframework.data.solr.core.query.result.HighlightPage;
import org.springframework.stereotype.Service;

@Service
public class ProductSearchService {

    private final SolrTemplate solrTemplate;

    public ProductSearchService(SolrTemplate solrTemplate) {
        this.solrTemplate = solrTemplate;
    }

    public HighlightPage<Product> search(String keyword, int page, int size) {
        Criteria titleCriteria = new Criteria("title").contains(keyword);
        Criteria descCriteria = new Criteria("description").contains(keyword);
        SimpleQuery query = new SimpleQuery(titleCriteria.or(descCriteria));
        query.setOffset((long) page * size);
        query.setRows(size);

        HighlightOptions highlightOptions = new HighlightOptions()
                .addField("title", "description")
                .setSimplePrefix("<em>")
                .setSimplePostfix("</em>");
        query.setHighlightOptions(highlightOptions);

        query.addSort(Sort.by(Sort.Direction.DESC, "price"));

        return solrTemplate.queryForHighlightPage("product", query, Product.class);
    }
}

上面的代码中,Criteria 的 or 连接表示标题或描述任一字段命中即可返回。分页参数 page 从 0 开始,size 控制每页条数。高亮结果会额外存放在 HighlightPage 中,每个实体的高亮片段需要通过 getHighlights 方法获取,而不是直接从实体字段读取。因此实际接口返回时,最好把高亮内容复制到 DTO 对象中再输出给前端。

如果索引数据量较大,建议在查询中限制返回字段,使用 query.addProjectionOnFields 指定需要的字段,减少网络传输和反序列化开销。对于关键词为空的情况,可以改成查询全部并分页,例如使用 new SimpleQuery(new Criteria()) 或者 new SimpleQuery().setOffset()。同时注意 Solr 默认最大查询行数限制,rows 过大可能被服务端拒绝。

五、暴露 REST 接口并处理常见问题

完成服务层后,通过 Controller 暴露一个搜索接口,方便通过浏览器或 Postman 验证。下面是一个简单的 GET 接口,接收 keyword、page、size 参数并返回 JSON。

import org.springframework.data.solr.core.query.result.HighlightPage;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/search")
public class SearchController {

    private final ProductSearchService searchService;

    public SearchController(ProductSearchService searchService) {
        this.searchService = searchService;
    }

    @GetMapping("/products")
    public HighlightPage<Product> search(
            @RequestParam String keyword,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        return searchService.search(keyword, page, size);
    }
}

实际联调时,如果出现中文搜索不到结果,通常不是配置错误,而是 Solr 默认字段类型 text_general 的中文分词效果不理想。text_general 对英文分词很好,但对中文可能按单字或整句切分,导致查询命中率低。解决方法是在 schema 中为中文字段指定使用 SmartChineseAnalyzer 对应的 fieldType,或者引入 IK Analyzer 插件后定义自定义 fieldType。改造 schema 后需要重建索引才能生效。

另一个常见问题是字段类型不匹配。例如 Java 实体中 price 定义为 Double,但 Solr 字段类型是 string,写入时虽然可能成功,但范围查询会按字符串排序,结果不符合预期。因此建议在实体注解中明确 type 参数,并在 schema 中使用 pdouble 或 pdoubles 类型。日志中如果看到类似错误,应检查字段类型映射是否一致。

Spring BootSpring Data Solr全文搜索修改时间:2026-10-02 17:34:01

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/1002/64763.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。