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

news/2025/9/20 22:48:17/文章来源:https://www.cnblogs.com/lxjshuju/p/19103001

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)的核心组件。

核心特性

适用场景

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

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

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

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

2. 环境准备

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

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 文档的唯一标识(相当于数据库的“主键”)
@Id
private 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:方便打印日志或调试时查看对象信息
@Override
public 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 等)*/@Repositorypublic 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)
@Autowired
private 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
{
@Autowired
private BookService bookService;
/**
* 1. 创建文档(POST 请求)
* @RequestBody:将请求体中的 JSON 数据转换为 Book 对象
* 响应:201 Created(创建成功)+ 新文档数据
*/
@PostMapping
public 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+数据,不存在返回 404
return book.isPresent() ? ResponseEntity.ok(book.get()) : ResponseEntity.notFound().build();
}
/**
* 3. 查询所有文档(GET 请求)
* 响应:200 OK + 所有文档列表
*/
@GetMapping
public 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. 不存在则返回 404
return 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
{
@Autowired
private BookService bookService;
// 测试用的书籍 id(用于后续查询、更新、删除)
private String testBookId;
// 测试前初始化:创建一条测试数据
@BeforeEach
void setUp() {
Book testBook = new Book("JUnit 测试书籍", "测试作者", 39, "2024-01-01");
Book savedBook = bookService.saveBook(testBook);
testBookId = savedBook.getId();
// 保存生成的 id
}
// 测试后清理:删除测试数据,避免影响其他测试
@AfterEach
void tearDown() {
bookService.deleteBookById(testBookId);
}
// 测试创建文档
@Test
void 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 查询文档
@Test
void testGetBookById() {
Optional<
Book> foundBook = bookService.getBookById(testBookId);
assertTrue(foundBook.isPresent());
// 验证文档存在
assertEquals("JUnit 测试书籍", foundBook.get().getTitle());
// 验证标题匹配
}
// 测试查询所有文档
@Test
void testGetAllBooks() {
Iterable<
Book> allBooks = bookService.getAllBooks();
assertTrue(allBooks.iterator().hasNext());
// 验证存在至少一条数据(即 setUp 中创建的测试数据)
}
// 测试根据作者查询文档
@Test
void testGetBooksByAuthor() {
List<
Book> booksByAuthor = bookService.getBooksByAuthor("测试作者");
assertFalse(booksByAuthor.isEmpty());
// 验证查询结果非空
// 验证所有结果的作者都是“测试作者”
for (Book book : booksByAuthor) {
assertEquals("测试作者", book.getAuthor());
}
}
// 测试根据标题关键字搜索
@Test
void testSearchBooksByTitle() {
List<
Book> searchedBooks = bookService.searchBooksByTitle("测试");
assertFalse(searchedBooks.isEmpty());
// 验证搜索结果非空
// 验证所有结果的标题包含“测试”
for (Book book : searchedBooks) {
assertTrue(book.getTitle().contains("测试"));
}
}
// 测试更新文档
@Test
void 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
}
// 测试删除文档
@Test
void 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://www.mzph.cn/news/908601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TypeScript - typeof 搭配 as const 技巧总结

这是一种 TypeScript 的高级类型技巧,用于从值推导出类型,实现类型和值的完美同步。 基本语法 const values = ["A", "B", "C"] as const; type ValueType = typeof values[number]; …

CentOS 8.5.2.111部署Zabbix6.0 手把手、保姆级

CentOS 8.5.2.111部署Zabbix6.0 手把手、保姆级CentOS 8.5.2.111部署Zabbix6.0 手把手、保姆级 前提、设置网络Ip地址等 cd /etc/sysconfig cd network-scripts/ ls vim ifcfg-enp0s3 systemctl restart NetworkManage…

[Linux/Docker] BusyBox : 开源、轻量级的Unix工具集

0 序 Docker时代,软件程序的最小化、轻量化部署趋势BusyBox 现在越来越流行,特别是在 Docker 用户中,许多 Docker 镜像使用 BusyBox 为你提供最小镜像。BusyBox := 原 Linux 发行版预装的 GNU Coreutils 在 Docker …

Part03 数据结构 - 教程

Part03 数据结构 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &qu…

图解3:幂等使用场景

幂等,API接口和MQ消费重复

推荐一款数据库安全产品:全知科技知形-数据库风险监测系统的价值解析

推荐一款数据库安全产品:全知科技知形-数据库风险监测系统的价值解析在当下数字经济快速发展的浪潮中,数据已被视为企业最核心的生产要素。无论是金融、医疗,还是互联网与制造业,数据库都是数据存储与流转的“中枢…

变量,常量,作用域

变量JAVA是一种强类型语言,每个都必须声明其类型。JAVA变量是程序中最基本的存储单位,其要素包括变量名,变量类型和作用域。 type varName [=value] [{,varName[=value]}]; //数据类型 变量名 = 值; 可以使用逗号隔…

wireshark 进行snmp 协议加密报文解密查看

转发请注明出处:在环境上进行对数通设备进行 snmp 采集数据,在现网运行环境中运行时,会偶尔出现异常,于是,采用tcpdump抓包,tcpdump 抓包得报文用wireshark打开之后,查询上报设备上报得数据层data格式如下:由于…

linux kernel synchronization 2

Per CPU VariablesA CPU should not access the elements of the array corresponding to other CPU. 每个CPU拥有该变量的独立副本 无需加锁 - 由于每个CPU只操作自己的副本,因此读写自己的副本时不会产生竞争条件 缓…

MySQL高阶查询语句与视图实战指南 - 指南

MySQL高阶查询语句与视图实战指南 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "M…

订单未支付多种方案

1、微服务常用MQ 2、单体情况下常用定时任务

耳鸣针灸学位

耳鸣针灸学位足驷马 中九里 灵骨 叉三 行间 肾关 太溪 牵引针患侧 听宫或者耳门

Twincat 中如何将位变量链接到字节

最近在测试一个EtherCAT IO模块, 参考视频Ethercat总线快速入门教程——1-2TwinCAT基本操作_哔哩哔哩_bilibili 我手里是欧辰的一个模块,它的输入输出都是字节形式的因此小改了下PLC程序 1. 在DUTs中新建了一个结构体…

不管不管,就要你的特殊对待(权限)

特殊权限,文件特殊属性除rwx(读写执行)三种文件权限外,还有哪些权限呢? 一.SUID 1.是什么? “以文件所有者的身份运行程序”。主要作用于可执行文件。 当一个可执行文件设置了 SUID 位时,任何用户在执行该文件时,…

202003_攻防世界_功夫再高也怕菜刀

流量分析,文件分离,WebShellTags:流量分析,文件分离,WebShell 0x00. 题目 附件路径:https://pan.baidu.com/s/1GyH7kitkMYywGC9YJeQLJA?pwd=Zmxh#list/path=/CTF附件 附件名称:202003_攻防世界_功夫再高也怕菜刀.zi…

工业软件:重塑协同流程、降低制造成本的关键器具

工业软件:重塑协同流程、降低制造成本的关键器具pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas",…

实用指南:【2025最新版】PCL点云处理算法汇总(C++长期更新版)

实用指南:【2025最新版】PCL点云处理算法汇总(C++长期更新版)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "C…

Gemini Proxy for Xcode 26

总的来说体验一塌糊涂,还不如Cursor/Trae或者是vscode装CLINE/RooCode等插件,更别提用Claude Code(虽然Xcode内置了,但是Claude Code官方明确不给中国大陆使用),需要一些手段来绕过进行使用, Xcode支持open AI 的一些接…