当前位置: 首页 > news >正文

Spring Boot 2.5.0 集成 Elasticsearch 7.12.0 实现 CRUD 完整指南(Windows 环境)

Spring Boot 2.5.0 集成 Elasticsearch 7.12.0 实现 CRUD 完整指南(Windows 环境)

目录

  1. Elasticsearch 简介

  2. 环境准备

  3. Elasticsearch 安装与启动

  4. Spring Boot 项目配置

  5. CRUD 核心代码实现

  6. CRUD 测试方法

  7. 常见问题排查

1. Elasticsearch 简介

Elasticsearch(简称 ES)是一款基于 Lucene 构建的分布式、高可用、实时的全文搜索引擎,同时也是 Elastic Stack(ELK Stack:Elasticsearch、Logstash、Kibana)的核心组件。

核心特性

  • 全文检索:支持对文本内容进行分词、模糊匹配、精准查询,适用于日志检索、商品搜索等场景;

  • 分布式架构:自动分片存储数据,支持水平扩展,可应对海量数据存储与高并发查询;

  • 实时响应:数据写入后近实时可查(默认 1 秒内),查询延迟低,满足实时业务需求;

  • 多数据类型支持:除文本外,还支持数值、日期、地理坐标等多种数据类型,适配复杂业务场景;

  • RESTful API:通过 HTTP 协议即可操作 ES,支持 JSON 格式交互,集成成本低。

适用场景

  • 电商平台商品搜索(如按名称、描述模糊查询);

  • 日志 / 监控数据存储与分析(如收集系统日志并快速检索异常信息);

  • 企业内部文档检索(如知识库、文档管理系统);

  • 实时数据分析(如用户行为数据实时统计)。

2. 环境准备

在开始集成前,确保本地环境满足以下条件:

  • JDK 版本:JDK 8 或 JDK 11(ES 7.12.0 依赖此版本范围,避免版本不兼容);

  • Spring Boot 版本:2.5.0(项目已指定 parent,无需额外修改版本);

  • Elasticsearch 版本:7.12.0(Windows 压缩包版,与 Spring Boot 2.5.0 兼容);

  • 开发工具:IntelliJ IDEA(或 Eclipse,推荐 IDEA 方便代码管理);

  • 测试工具:Postman(或 Swagger、curl,用于测试 API 接口)。

3. Elasticsearch 安装与启动

3.1 下载与解压

直接安装 7.12.0 版本:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-7-12-0

  1. 访问 Elasticsearch 历史版本下载页:https://www.elastic.co/cn/downloads/past-releases#elasticsearch;

  2. 找到 7.12.0 版本,选择 Windows 系统的压缩包(elasticsearch-7.12.0-windows-x86_64.zip)下载;

  3. 解压到 无中文、无空格 的目录(例如 D:\elasticsearch-7.12.0,路径含特殊字符会导致启动失败)。

3.2 启动 Elasticsearch 服务

  1. 进入解压目录下的 bin 文件夹(完整路径:D:\elasticsearch-7.12.0\bin);

  2. 双击 elasticsearch.bat 文件,自动弹出命令行窗口(不要关闭此窗口,关闭即停止服务);

  3. 等待启动完成:当命令行输出 started 字样,且无报错信息时,说明服务启动成功(首次启动约 10-30 秒)。

3.3 验证启动状态

  1. 打开浏览器,访问 http://localhost:9200(ES 默认 HTTP 端口为 9200);

  2. 若返回以下 JSON 响应,证明 ES 服务正常运行:

{"name" : "DESKTOP-XXXXXX",  // 你的电脑名称"cluster_name" : "elasticsearch",  // 默认集群名称"cluster_uuid" : "XXXXXXXXXXXXXXXXXXXXX","version" : {"number" : "7.12.0",  // ES 版本,需与下载一致"build_flavor" : "default","build_type" : "zip","build_hash" : "78722783c38caa25a709d81e9ec61e65bde69113","build_date" : "2021-03-18T06:17:15.410153305Z","build_snapshot" : false,"lucene_version" : "8.8.0","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search"
}

4. Spring Boot 项目配置

4.1 添加依赖(pom.xml)

在项目的 pom.xml 中,补充 Elasticsearch 及相关依赖(已有 parent 无需额外指定版本):

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.0</version><relativePath/>
</parent><!-- Spring Boot Data Elasticsearch:提供 ES 数据访问能力 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency><!-- Jackson:处理 JSON 格式转换(实体类与 ES 文档交互) -->
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId>
</dependency><!-- 可选:Swagger3:生成 API 文档,方便网页端测试 -->
<dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version>
</dependency>

4.2 配置 ES 连接(application.properties)

src/main/resources/application.properties 中,添加 ES 连接参数:

# ES 服务地址(默认 9200 端口,多个地址用逗号分隔)
spring.elasticsearch.rest.uris=http://localhost:9200# 连接超时时间(1秒,避免长时间等待)
spring.elasticsearch.rest.connection-timeout=1s# 读取超时时间(3秒,适配大数据量查询)
spring.elasticsearch.rest.read-timeout=3s# 可选:日志配置(调试时开启,查看 ES 交互细节)
logging.level.org.springframework.data.elasticsearch=DEBUG
logging.level.org.elasticsearch=DEBUG

5. CRUD 核心代码实现

以「书籍(Book)」为业务模型,实现 ES 文档的 Create(创建)、Read(查询)、Update(更新)、Delete(删除) 操作,代码遵循「实体类 → Repository → Service → Controller」分层设计。

5.1 实体类(Book.java)

定义 ES 文档结构,通过注解映射索引、字段类型及分词规则:

package com.example.demo.model;import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;/*** @Document:指定 ES 索引名称(相当于数据库的“表”)* indexName:索引名,建议小写;shards:分片数(默认5);replicas:副本数(默认1)*/
@Document(indexName = "books", shards = 1, replicas = 0)
public class Book {// @Id:ES 文档的唯一标识(相当于数据库的“主键”)@Idprivate String id;/*** @Field:配置字段属性* type:字段类型(Text 支持分词,Keyword 不支持分词)* analyzer:分词器(ik_max_word 为 IK 分词器细粒度分词,适合全文检索)* searchAnalyzer:查询时使用的分词器(与 analyzer 一致即可)*/@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")private String title;  // 书籍标题@Field(type = FieldType.Text, analyzer = "ik_max_word")private String author; // 书籍作者// 数值类型:无需分词,直接存储@Field(type = FieldType.Integer)private Integer price; // 书籍价格// 日期类型:指定格式,避免 ES 自动转换@Field(type = FieldType.Date, format = {}, pattern = "yyyy-MM-dd")private String publishDate; // 出版日期// 无参构造:Spring Data 要求必须存在public Book() {}// 有参构造:快速创建 Book 对象public Book(String title, String author, Integer price, String publishDate) {this.title = title;this.author = author;this.price = price;this.publishDate = publishDate;}// Getter 和 Setter(必须生成,否则无法注入数据)public String getId() { return id; }public void setId(String id) { this.id = id; }public String getTitle() { return title; }public void setTitle(String title) { this.title = title; }public String getAuthor() { return author; }public void setAuthor(String author) { this.author = author; }public Integer getPrice() { return price; }public void setPrice(Integer price) { this.price = price; }public String getPublishDate() { return publishDate; }public void setPublishDate(String publishDate) { this.publishDate = publishDate; }// toString:方便打印日志或调试时查看对象信息@Overridepublic String toString() {return "Book{" +"id='" + id + '\'' +", title='" + title + '\'' +", author='" + author + '\'' +", price=" + price +", publishDate='" + publishDate + '\'' +'}';}
}

说明:若需使用 IK 分词器,需先在 ES 中安装(步骤见 7.1 常见问题)。

5.2 Repository 接口(BookRepository.java)

继承 ElasticsearchRepository,Spring Data 会自动实现 CRUD 基础方法,无需手动编写查询逻辑:

package com.example.demo.repository;import com.example.demo.model.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;import java.util.List;/*** @Repository:标记为数据访问层组件,让 Spring 自动扫描注入* ElasticsearchRepository<实体类, 主键类型>:提供基础 CRUD 方法(save、findById、delete 等)*/
@Repository
public interface BookRepository extends ElasticsearchRepository<Book, String> {// 自定义查询方法:根据作者查询书籍(Spring Data 自动解析方法名生成 ES 查询)List<Book> findByAuthor(String author);// 自定义查询方法:根据标题包含关键字查询(Containing 相当于“LIKE %关键字%”)List<Book> findByTitleContaining(String keyword);// 自定义查询方法:根据价格范围查询(Between 对应 ES 的范围查询)List<Book> findByPriceBetween(Integer minPrice, Integer maxPrice);
}

5.3 Service 层(BookService.java)

封装业务逻辑,调用 Repository 实现 CRUD 操作,解耦 Controller 与数据访问层:

package com.example.demo.service;import com.example.demo.model.Book;
import com.example.demo.repository.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.Optional;/*** @Service:标记为业务逻辑层组件,Spring 自动扫描注入*/
@Service
public class BookService {// 注入 Repository 依赖(Spring 自动完成,无需手动 new)@Autowiredprivate BookRepository bookRepository;/*** 1. Create/Update:创建或更新文档* 逻辑:若 id 存在则更新,不存在则创建新文档*/public Book saveBook(Book book) {return bookRepository.save(book);}/*** 2. Read:根据 id 查询单个文档* 返回 Optional<Book>:避免空指针,需通过 isPresent() 判断是否存在*/public Optional<Book> getBookById(String id) {return bookRepository.findById(id);}/*** 3. Read:查询所有文档* 返回 Iterable<Book>:支持迭代遍历所有文档*/public Iterable<Book> getAllBooks() {return bookRepository.findAll();}/*** 4. Read:根据作者查询文档*/public List<Book> getBooksByAuthor(String author) {return bookRepository.findByAuthor(author);}/*** 5. Read:根据标题关键字搜索文档*/public List<Book> searchBooksByTitle(String keyword) {return bookRepository.findByTitleContaining(keyword);}/*** 6. Delete:根据 id 删除文档*/public void deleteBookById(String id) {bookRepository.deleteById(id);}
}

5.4 Controller 层(BookController.java)

提供 RESTful API 接口,供外部调用(如 Postman、前端页面),接收请求并返回响应:

   package com.example.demo.controller;import com.example.demo.model.Book;
import com.example.demo.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import java.util.List;
import java.util.Optional;/*** @RestController:标记为 REST 接口控制器(返回 JSON 数据,而非页面)* @RequestMapping:指定接口基础路径(所有接口前缀为 /api/books)*/
@RestController
@RequestMapping("/api/books")
public class BookController {@Autowiredprivate BookService bookService;/*** 1. 创建文档(POST 请求)* @RequestBody:将请求体中的 JSON 数据转换为 Book 对象* 响应:201 Created(创建成功)+ 新文档数据*/@PostMappingpublic ResponseEntity<Book> createBook(@RequestBody Book book) {Book savedBook = bookService.saveBook(book);return new ResponseEntity<>(savedBook, HttpStatus.CREATED);}/*** 2. 根据 id 查询文档(GET 请求)* @PathVariable:从 URL 路径中获取 id 参数(如 /api/books/123 中的 123)* 响应:200 OK(存在)/ 404 Not Found(不存在)*/@GetMapping("/{id}")public ResponseEntity<Book> getBookById(@PathVariable String id) {Optional<Book> book = bookService.getBookById(id);// 三元表达式:存在则返回 200+数据,不存在返回 404return book.isPresent() ? ResponseEntity.ok(book.get()) : ResponseEntity.notFound().build();}/*** 3. 查询所有文档(GET 请求)* 响应:200 OK + 所有文档列表*/@GetMappingpublic ResponseEntity<Iterable<Book>> getAllBooks() {return ResponseEntity.ok(bookService.getAllBooks());}/*** 4. 根据作者查询文档(GET 请求)* @PathVariable:从 URL 路径中获取 author 参数* 响应:200 OK + 符合条件的文档列表*/@GetMapping("/author/{author}")public ResponseEntity<List<Book>> getBooksByAuthor(@PathVariable String author) {return ResponseEntity.ok(bookService.getBooksByAuthor(author));}/*** 5. 根据标题关键字搜索(GET 请求)* 响应:200 OK + 符合条件的文档列表*/@GetMapping("/search/title/{keyword}")public ResponseEntity<List<Book>> searchBooksByTitle(@PathVariable String keyword) {return ResponseEntity.ok(bookService.searchBooksByTitle(keyword));}/*** 6. 更新文档(PUT 请求)* 逻辑:先查询 id 是否存在,存在则更新,不存在返回 404* 响应:200 OK(更新成功)/ 404 Not Found(文档不存在)*/@PutMapping("/{id}")public ResponseEntity<Book> updateBook(@PathVariable String id, @RequestBody Book book) {// 1. 先查询文档是否存在Optional<Book> existingBook = bookService.getBookById(id);if (existingBook.isPresent()) {// 2. 存在则设置 id(避免更新时生成新文档),再执行更新book.setId(id);Book updatedBook = bookService.saveBook(book);return ResponseEntity.ok(updatedBook);} else {// 3. 不存在则返回 404return ResponseEntity.notFound().build();}}/*** 7. 删除文档(DELETE 请求)* 逻辑:先查询 id 是否存在,存在则删除,不存在返回 404* 响应:204 No Content(删除成功,无返回内容)/ 404 Not Found(文档不存在)*/@DeleteMapping("/{id}")public ResponseEntity<Void> deleteBook(@PathVariable String id) {if (bookService.getBookById(id).isPresent()) {bookService.deleteBookById(id);// 204 状态码:表示请求成功但无响应体return new ResponseEntity<>(HttpStatus.NO_CONTENT);} else {return ResponseEntity.notFound().build();}}
}

6. CRUD 测试方法

测试前需确保两个服务正常运行:

  1. Elasticsearch 服务(http://localhost:9200 可访问);

  2. Spring Boot 应用(默认端口 8080,无端口冲突)。

6.1 方法 1:使用 Postman 测试(推荐)

打开 Postman,按照以下用例测试所有 CRUD 接口,每个接口的请求参数和预期结果如下:

接口功能请求方式请求 URL请求体(JSON)预期响应状态码预期响应内容
创建书籍POSThttp://localhost:8080/api/books{"title":"Spring Boot实战","author":"张三","price":59,"publishDate":"2020-01-15"}201 Created返回创建的书籍完整信息(含自动生成的 id)
根据 id 查询书籍GEThttp://localhost:8080/api/books/1无(将 1 替换为创建时返回的 id)200 OK(存在)返回对应 id 的书籍信息
查询所有书籍GEThttp://localhost:8080/api/books200 OK返回所有已创建的书籍列表
根据作者查询GEThttp://localhost:8080/api/books/author/张三200 OK返回所有 “张三” 创作的书籍
标题关键字搜索GEThttp://localhost:8080/api/books/search/title/Spring200 OK返回标题包含 “Spring” 的书籍
更新书籍PUThttp://localhost:8080/api/books/1{"title":"Spring Boot实战(第二版)","author":"张三","price":69,"publishDate":"2021-05-20"}200 OK(存在)返回更新后的书籍信息
删除书籍DELETEhttp://localhost:8080/api/books/1204 No Content(存在)无响应体,仅返回状态码

注意:若测试 “根据 id 查询 / 更新 / 删除” 时,id 不存在,响应状态码会返回 404 Not Found,属于正常现象。

6.2 方法 2:使用 Swagger 测试(网页端)

若已添加 Swagger 依赖和配置,可通过网页直接测试接口,步骤如下:

  1. 启动 Spring Boot 应用后,访问 Swagger 文档地址:http://localhost:8080/swagger-ui/index.html

  2. 页面会显示所有 /api/books 前缀的接口,点击任意接口名称(如 POST /api/books)展开详情;

  3. 点击「Try it out」按钮,输入请求参数(如创建书籍时的 JSON 数据);

  4. 点击「Execute」按钮执行请求,下方会显示响应状态码和响应内容,无需手动拼接 URL。

6.3 方法 3:使用 JUnit 单元测试(自动化验证)

编写单元测试类,直接测试 Service 层逻辑,无需依赖外部工具,步骤如下:

6.3.1 测试类代码(BookServiceTest.java)
package com.example.demo.service;import com.example.demo.model.Book;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;
import java.util.Optional;import static org.junit.jupiter.api.Assertions.*;// 启动 Spring Boot 上下文,用于注入依赖
@SpringBootTest
public class BookServiceTest {@Autowiredprivate BookService bookService;// 测试用的书籍 id(用于后续查询、更新、删除)private String testBookId;// 测试前初始化:创建一条测试数据@BeforeEachvoid setUp() {Book testBook = new Book("JUnit 测试书籍", "测试作者", 39, "2024-01-01");Book savedBook = bookService.saveBook(testBook);testBookId = savedBook.getId(); // 保存生成的 id}// 测试后清理:删除测试数据,避免影响其他测试@AfterEachvoid tearDown() {bookService.deleteBookById(testBookId);}// 测试创建文档@Testvoid testSaveBook() {Book newBook = new Book("新测试书籍", "新作者", 49, "2024-02-02");Book savedBook = bookService.saveBook(newBook);assertNotNull(savedBook.getId()); // 验证 id 非空(创建成功)assertEquals("新测试书籍", savedBook.getTitle()); // 验证标题正确// 清理测试数据bookService.deleteBookById(savedBook.getId());}// 测试根据 id 查询文档@Testvoid testGetBookById() {Optional<Book> foundBook = bookService.getBookById(testBookId);assertTrue(foundBook.isPresent()); // 验证文档存在assertEquals("JUnit 测试书籍", foundBook.get().getTitle()); // 验证标题匹配}// 测试查询所有文档@Testvoid testGetAllBooks() {Iterable<Book> allBooks = bookService.getAllBooks();assertTrue(allBooks.iterator().hasNext()); // 验证存在至少一条数据(即 setUp 中创建的测试数据)}// 测试根据作者查询文档@Testvoid testGetBooksByAuthor() {List<Book> booksByAuthor = bookService.getBooksByAuthor("测试作者");assertFalse(booksByAuthor.isEmpty()); // 验证查询结果非空// 验证所有结果的作者都是“测试作者”for (Book book : booksByAuthor) {assertEquals("测试作者", book.getAuthor());}}// 测试根据标题关键字搜索@Testvoid testSearchBooksByTitle() {List<Book> searchedBooks = bookService.searchBooksByTitle("测试");assertFalse(searchedBooks.isEmpty()); // 验证搜索结果非空// 验证所有结果的标题包含“测试”for (Book book : searchedBooks) {assertTrue(book.getTitle().contains("测试"));}}// 测试更新文档@Testvoid testUpdateBook() {// 1. 查询测试数据Optional<Book> bookToUpdate = bookService.getBookById(testBookId);assertTrue(bookToUpdate.isPresent());// 2. 修改价格Book updatedBook = bookToUpdate.get();updatedBook.setPrice(59);bookService.saveBook(updatedBook);// 3. 验证更新结果Optional<Book> result = bookService.getBookById(testBookId);assertEquals(59, result.get().getPrice()); // 价格已从 39 改为 59}// 测试删除文档@Testvoid testDeleteBookById() {// 1. 删除测试数据bookService.deleteBookById(testBookId);// 2. 验证删除结果Optional<Book> deletedBook = bookService.getBookById(testBookId);assertFalse(deletedBook.isPresent()); // 验证文档已不存在}
}
6.3.2 运行测试
  1. 在 IDEA 中打开 BookServiceTest.java

  2. 右键点击类名,选择「Run ‘BookServiceTest’」;

  3. 等待测试完成,若所有测试方法前显示绿色对勾,说明 CRUD 逻辑全部正常。

7. 常见问题排查

在集成或测试过程中,可能会遇到以下问题,可按对应的解决方案排查:

7.1 问题 1:启动 Spring Boot 应用时,报错 “找不到 IK 分词器”

报错信息Elasticsearch exception [type=illegal_argument_exception, reason=failed to find analyzer [ik_max_word]]

原因:实体类中使用了 analyzer = "ik_max_word"(IK 分词器),但 ES 未安装该插件。

解决方案

  1. 下载 IK 分词器插件(需与 ES 版本一致,即 7.12.0):

    下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.12.0,选择 elasticsearch-analysis-ik-7.12.0.zip

  2. 在 ES 安装目录下,新建 plugins/ik 文件夹(路径:D:\elasticsearch-7.12.0\plugins\ik);

  3. 将下载的压缩包解压到 ik 文件夹中;

  4. 重启 Elasticsearch 服务,IK 分词器会自动加载。

7.2 问题 2:访问 http://localhost:9200 时,提示 “连接拒绝”

原因:ES 服务未启动,或端口被占用。

解决方案

  1. 检查 ES 启动窗口是否正常运行(未关闭且无报错);

  2. 若 ES 已启动,打开命令提示符(CMD),执行 netstat -ano | findstr "9200",查看 9200 端口是否被其他进程占用;

  3. 若端口被占用,结束占用进程(通过任务管理器,根据 PID 找到对应进程),或修改 ES 端口(在 config/elasticsearch.yml 中添加 http.port: 9201,重启 ES)。

7.3 问题 3:测试 “创建书籍” 时,响应状态码 500,报错 “连接超时”

报错信息Elasticsearch exception [type=connect_timeout_exception, reason=connect timed out]

原因:Spring Boot 应用无法连接到 ES 服务。

解决方案

  1. 确认 ES 服务已启动,且 http://localhost:9200 可访问;

  2. 检查 application.properties 中的 spring.elasticsearch.rest.uris 配置是否正确(是否为 http://localhost:9200,无多余空格或符号);

  3. 若 ES 端口已修改(如改为 9201),需同步更新该配置为 http://localhost:9201

7.4 问题 4:单元测试时,报错 “无法注入 BookService”

报错信息No qualifying bean of type 'com.example.demo.service.BookService' available

原因:Spring 未扫描到 Service 组件,可能是包路径配置错误。

解决方案

  1. 检查 Spring Boot 启动类(如 DemoApplication.java)是否添加了 @SpringBootApplication 注解;

  2. 确保启动类所在的包是所有业务类(Service、Controller、Repository)的父包,例如:

  • 启动类路径:com.example.demo

  • Service 路径:com.example.demo.service(子包,可被扫描);

  1. 若包路径不满足父子关系,可在启动类上添加 @ComponentScan(basePackages = "com.example.demo"),指定扫描的包范围。

文章转载自:

http://brYJNY7p.bzsqr.cn
http://rMhyXIAp.bzsqr.cn
http://US5ciMkl.bzsqr.cn
http://1gZbS71S.bzsqr.cn
http://tEctwEPe.bzsqr.cn
http://YZNvVFGX.bzsqr.cn
http://ZYYj5ytx.bzsqr.cn
http://qh2Dnlfo.bzsqr.cn
http://xAMeddqj.bzsqr.cn
http://N8IeaEzx.bzsqr.cn
http://cfjdE5UN.bzsqr.cn
http://LI5US72s.bzsqr.cn
http://6o9uKaFS.bzsqr.cn
http://WWoXoKhe.bzsqr.cn
http://PSQcFmEv.bzsqr.cn
http://swVfMqbw.bzsqr.cn
http://io2XVNst.bzsqr.cn
http://ys7hPzxj.bzsqr.cn
http://opzo2oNe.bzsqr.cn
http://SOfZcbvt.bzsqr.cn
http://PrXxThBJ.bzsqr.cn
http://LWSRPNJN.bzsqr.cn
http://XpDnBfov.bzsqr.cn
http://FEogz6RC.bzsqr.cn
http://0gQ6Zjaq.bzsqr.cn
http://9YcDsFGa.bzsqr.cn
http://UwJb1J9g.bzsqr.cn
http://5HNW97Yu.bzsqr.cn
http://gUjg9x40.bzsqr.cn
http://Sq6dNouW.bzsqr.cn
http://www.dtcms.com/a/385869.html

相关文章:

  • 第九章:使用Jmeter+Ant+Jenkins实现接口自动化测试持续集成
  • 使用IP的好处
  • 育碧确定《AC影》3月20日发售并分享系列游戏首发数据
  • 容器热升级机制在云服务器零停机部署中的实施规范
  • 贪心算法应用:时间序列分段(PAA)问题详解
  • 微信小程序开发教程(十五)
  • 语音DDS系统架构与实现方案:车机与手机语音助手的差异分析
  • 手机群控平台的工作效率
  • DBAPI免费版对比apiSQL免费版
  • node.js在vscode中npm等出现的一个问题
  • node.js学习笔记:中间件
  • Debian更新安全补丁常用命令
  • LeetCode:6.三数之和
  • 号称用rust重写的sqlite数据库tursodb与sqlite及duckdb性能比较
  • cuda stream
  • 云计算在云手机中的作用
  • C++STL学习:unordered_set/unordered_map
  • RTOS 任务状态与调度机制详解
  • 基于 Java EE+MySQL+Dart 实现多平台应用的音乐共享社区
  • 解密Tomcat的I/O模型:非阻塞之上,为何要兼容阻塞?
  • 时序数据库IoTDB如何支撑万亿级设备连接?
  • 订阅式红队专家服务:下一代网络安全评估新模式
  • 大模型数据处理实战:文本处理、高效数据管道、性能优化技巧、多机分布式、质量评估,全方位解析
  • 基于pyspark的双十一美妆数据分析及可视化
  • 基于Vue3的人工智能生成内容标识服务平台前端页面设计
  • 域名市场中,如何确认域名的价值
  • Linux 文件归档和备份
  • 基于Vue的教师档案管理系统的设计与实现
  • 整洁架构之道笔记
  • 深度学习预知识