GLM-OCR Java后端集成教程:SpringBoot调用OCR API服务
GLM-OCR Java后端集成教程SpringBoot调用OCR API服务你是不是也遇到过这样的场景用户上传了一堆发票、合同或者名片图片你需要快速地把里面的文字信息提取出来然后存到数据库里做进一步处理。手动录入效率太低还容易出错。这时候一个稳定可靠的OCR光学字符识别服务就成了后端开发的刚需。最近我在一个SpringBoot项目里集成了GLM-OCR服务用它来处理用户上传的各种文档图片效果挺不错的。今天我就把自己从零开始搭建、调试到最终上线的整个过程分享出来手把手带你走一遍。就算你之前没怎么接触过OCR接口调用跟着这篇教程也能搞定。我们的目标很明确在SpringBoot项目里实现一个能接收图片文件、调用GLM-OCR接口识别文字、并把结果异步存入MySQL数据库的完整服务。还会加上接口限流和日志监控让它更健壮。好了咱们开始吧。1. 环境准备与项目搭建在开始写代码之前咱们先把“战场”打扫干净把需要的工具和环境准备好。这个过程不复杂跟着步骤来就行。1.1 你需要准备什么首先确保你的电脑上已经安装了下面这几样东西。如果还没装先去官网下载安装一下都很简单。Java开发环境JDK 8 或以上版本。我用的JDK 11比较稳定。安装完记得配置好JAVA_HOME环境变量。项目管理工具Maven 3.6 或者 Gradle。这篇教程我用Maven来演示它的pom.xml配置文件大家比较熟悉。代码编辑器IntelliJ IDEA、Eclipse或者VS Code都可以选你顺手的。我个人推荐IDEA对SpringBoot支持特别好。数据库MySQL 5.7 或 8.0。咱们用来存识别后的文本结果。网络确保你的开发机器能正常访问GLM-OCR服务的API地址。这个通常需要你事先申请好API Key拿到调用权限。1.2 创建SpringBoot项目打开你的IDE我用IDEA演示。选择新建一个Spring Initializr项目。选择依赖在依赖选择页面勾选我们需要的“起步依赖”Spring Web用来构建RESTful API。Spring Data JPA简化数据库操作。MySQL Driver连接MySQL数据库。Lombok一个神器能通过注解自动生成getter、setter等方法让代码更简洁。这个不是必须的但用了就回不去了。生成项目选好依赖后点击生成IDE会自动下载并创建一个基础项目结构。项目创建好后打开根目录下的pom.xml文件你应该能看到刚才选的依赖都已经在里面了。为了后续调用HTTP接口和做限流我们还需要手动加两个依赖。打开pom.xml在dependencies标签里添加!-- 用于HTTP服务调用二选一即可 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-webflux/artifactId !-- 如果你用WebClient -- /dependency !-- 或者 -- !-- dependency groupIdorg.springframework/groupId artifactIdspring-web/artifactId !- 如果只用RestTemplate - /dependency -- !-- 限流用的Guava RateLimiter -- dependency groupIdcom.google.guava/groupId artifactIdguava/artifactId version31.1-jre/version !-- 请使用最新稳定版 -- /dependency这里我建议用WebClient它是Spring 5以后推荐的响应式HTTP客户端功能更现代。当然用传统的RestTemplate也完全没问题看你的习惯。2. 核心概念与流程设计在动手写代码前花几分钟理清思路很重要。咱们先看看整个服务是怎么运转的心里有个谱。2.1 服务调用流程整个过程就像一条流水线用户上传用户通过前端页面或者App上传一张或多张图片到我们的SpringBoot服务。接收与校验我们的Controller接口接收到图片文件先做简单的格式、大小校验。调用OCR服务把图片文件或Base64编码后的数据通过HTTP请求发送给GLM-OCR的API接口。处理响应拿到OCR接口返回的JSON数据里面包含了识别出的文本、文字位置等信息。我们把需要的文本内容解析出来。异步存储为了不阻塞接口响应我们把“保存到数据库”这个任务扔到一个异步线程池里去执行。返回结果告诉用户“识别任务已提交成功”并返回一个任务ID之类的东西方便用户后续查询结果。2.2 数据库表设计我们需要一张表来保存识别结果。设计很简单在src/main/resources目录下创建一个schema.sql文件如果用了JPA的自动建表也可以不用这个文件。CREATE TABLE IF NOT EXISTS ocr_result ( id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 主键ID, task_id VARCHAR(64) NOT NULL COMMENT 任务唯一标识, original_filename VARCHAR(255) COMMENT 原始文件名, file_size BIGINT COMMENT 文件大小(字节), recognized_text LONGTEXT COMMENT 识别出的文本内容, confidence_score DECIMAL(5,2) COMMENT 识别置信度如果有, api_response TEXT COMMENT 原始的API响应JSON用于调试, status VARCHAR(20) DEFAULT SUCCESS COMMENT 状态SUCCESS, FAILED, error_message TEXT COMMENT 如果失败错误信息, created_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, INDEX idx_task_id (task_id), INDEX idx_created_time (created_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENTOCR识别结果表;字段解释task_id每次识别请求我们生成一个唯一ID方便追踪。recognized_text用LONGTEXT类型因为有些文档识别出来的文本可能很长。api_response把OCR接口返回的原始JSON存下来万一识别结果有问题可以回头查原始数据非常有用。status记录这次调用是成功还是失败。3. 分步实践编写核心代码好了铺垫做完进入最核心的编码环节。我会把关键代码都贴出来并加上详细注释。3.1 配置文件和实体类首先把一些配置信息放到application.yml或application.properties里。# application.yml spring: datasource: url: jdbc:mysql://localhost:3306/your_database?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: your_username password: your_password driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update # 根据实体类自动更新表结构生产环境建议用none或validate show-sql: true # 开发时显示SQL方便调试 glm: ocr: api-url: https://your-glm-ocr-service.com/v1/ocr # 替换为真实的OCR API地址 api-key: your-api-key-here # 替换为你的API Key timeout: 10000 # 调用超时时间单位毫秒 # 文件上传大小限制 spring: servlet: multipart: max-file-size: 10MB max-request-size: 20MB # 异步线程池配置 async: executor: thread: core-pool-size: 5 max-pool-size: 20 queue-capacity: 100接着创建对应的实体类OcrResult.java。package com.yourproject.entity; import lombok.Data; import javax.persistence.*; import java.time.LocalDateTime; Entity Table(name ocr_result) Data // Lombok注解自动生成getter, setter, toString等 public class OcrResult { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; Column(nullable false, length 64) private String taskId; private String originalFilename; private Long fileSize; Lob // 对应数据库的LONGTEXT类型 Column(columnDefinition LONGTEXT) private String recognizedText; private Double confidenceScore; Lob Column(columnDefinition TEXT) private String apiResponse; private String status SUCCESS; private String errorMessage; Column(updatable false) private LocalDateTime createdTime LocalDateTime.now(); // 可以加一个预处理方法确保保存前taskId不为空如果需要 PrePersist public void prePersist() { if (this.createdTime null) { this.createdTime LocalDateTime.now(); } } }3.2 调用OCR服务WebClient方式我们来创建一个服务类专门负责和GLM-OCR API打交道。这里用WebClient。package com.yourproject.service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ByteArrayResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.client.MultipartBodyBuilder; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import java.io.IOException; import java.time.Duration; Service Slf4j public class GlmOcrService { Value(${glm.ocr.api-url}) private String apiUrl; Value(${glm.ocr.api-key}) private String apiKey; Value(${glm.ocr.timeout:10000}) private int timeout; private final WebClient webClient; private final ObjectMapper objectMapper; // 构造方法初始化WebClient public GlmOcrService(ObjectMapper objectMapper) { this.objectMapper objectMapper; this.webClient WebClient.builder() .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) .defaultHeader(Authorization, Bearer apiKey) // 假设使用Bearer Token认证 .build(); } /** * 调用OCR接口识别图片中的文字 * param fileBytes 图片文件的字节数组 * param filename 文件名 * return 识别出的文本内容 */ public MonoString recognizeText(byte[] fileBytes, String filename) { MultipartBodyBuilder builder new MultipartBodyBuilder(); // 根据OCR API的要求添加参数这里假设需要一个名为image的文件字段 builder.part(image, new ByteArrayResource(fileBytes) { Override public String getFilename() { return filename; } }); log.info(调用GLM-OCR API文件名: {}, filename); return webClient.post() .uri(apiUrl) .body(BodyInserters.fromMultipartData(builder.build())) .retrieve() .bodyToMono(String.class) // 先接收为字符串 .timeout(Duration.ofMillis(timeout)) .doOnError(e - log.error(调用OCR API失败文件名: {}, filename, e)) .flatMap(responseBody - { try { // 解析JSON响应这里需要根据GLM-OCR返回的实际格式调整 JsonNode rootNode objectMapper.readTree(responseBody); // 假设返回格式为 { code: 0, data: { text: 识别出的文字 } } if (rootNode.path(code).asInt() 0) { String text rootNode.path(data).path(text).asText(); return Mono.just(text); } else { String errorMsg rootNode.path(message).asText(未知错误); log.warn(OCR API返回错误: {}, errorMsg); return Mono.error(new RuntimeException(OCR识别失败: errorMsg)); } } catch (IOException e) { log.error(解析OCR响应JSON失败, e); return Mono.error(new RuntimeException(解析响应失败)); } }); } }代码解释我们用Value注解从配置文件里读取API地址和密钥。在构造方法里初始化了一个配置好默认请求头的WebClient。recognizeText方法是核心它构建一个包含图片文件的表单请求发送给OCR接口。使用timeout方法设置超时避免网络问题导致线程长时间挂起。解析响应JSON时这里需要你根据GLM-OCR接口实际的返回格式来调整rootNode.path(...)的路径。重点就是找到存放识别文本的那个字段。3.3 控制器与异步处理现在创建控制器Controller来接收前端上传并利用Spring的异步能力处理存储。首先配置一个异步线程池。在配置类AsyncConfig.java中package com.yourproject.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; Configuration EnableAsync public class AsyncConfig { Bean(name taskExecutor) public Executor taskExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(20); executor.setQueueCapacity(100); executor.setThreadNamePrefix(OCR-Async-); executor.initialize(); return executor; } }然后创建数据访问层和业务层。为了简洁这里用一个Service类包含存储逻辑。package com.yourproject.service; import com.yourproject.entity.OcrResult; import com.yourproject.repository.OcrResultRepository; // 需要你创建这个JPA Repository接口 import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.concurrent.CompletableFuture; Service Slf4j RequiredArgsConstructor public class OcrResultService { private final OcrResultRepository ocrResultRepository; /** * 异步保存识别结果到数据库 */ Async(taskExecutor) // 指定使用我们配置的线程池 public CompletableFutureOcrResult saveResultAsync(OcrResult result) { log.info(开始异步保存OCR结果任务ID: {}, result.getTaskId()); try { OcrResult saved ocrResultRepository.save(result); log.info(异步保存OCR结果成功任务ID: {}, saved.getTaskId()); return CompletableFuture.completedFuture(saved); } catch (Exception e) { log.error(异步保存OCR结果失败任务ID: {}, result.getTaskId(), e); // 这里可以根据需要处理失败逻辑比如存入一个失败队列 return CompletableFuture.failedFuture(e); } } }最后创建控制器OcrController.java把上传、识别、异步存储串联起来。package com.yourproject.controller; import com.yourproject.entity.OcrResult; import com.yourproject.service.GlmOcrService; import com.yourproject.service.OcrResultService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import reactor.core.publisher.Mono; import java.util.UUID; import java.util.concurrent.CompletableFuture; RestController RequestMapping(/api/ocr) RequiredArgsConstructor Slf4j public class OcrController { private final GlmOcrService glmOcrService; private final OcrResultService ocrResultService; PostMapping(/recognize) public MonoResponseEntity? recognizeImage(RequestParam(file) MultipartFile file) { if (file.isEmpty()) { return Mono.just(ResponseEntity.badRequest().body(请上传文件)); } String taskId UUID.randomUUID().toString(); String filename file.getOriginalFilename(); log.info(收到OCR识别请求任务ID: {}, 文件名: {}, taskId, filename); try { byte[] fileBytes file.getBytes(); // 1. 调用OCR服务 return glmOcrService.recognizeText(fileBytes, filename) .flatMap(recognizedText - { // 2. 构建实体对象 OcrResult result new OcrResult(); result.setTaskId(taskId); result.setOriginalFilename(filename); result.setFileSize(file.getSize()); result.setRecognizedText(recognizedText); result.setStatus(SUCCESS); // 3. 异步保存到数据库不等待完成 ocrResultService.saveResultAsync(result); // 4. 立即返回成功响应 return Mono.just(ResponseEntity.ok() .body(识别任务已提交任务ID: taskId)); }) .onErrorResume(e - { // 处理识别失败的情况 log.error(OCR识别过程出错任务ID: {}, taskId, e); OcrResult failedResult new OcrResult(); failedResult.setTaskId(taskId); failedResult.setOriginalFilename(filename); failedResult.setStatus(FAILED); failedResult.setErrorMessage(e.getMessage()); ocrResultService.saveResultAsync(failedResult); // 异步保存失败记录 return Mono.just(ResponseEntity.status(500) .body(识别失败: e.getMessage())); }); } catch (IOException e) { log.error(读取上传文件失败, e); return Mono.just(ResponseEntity.status(500).body(文件处理失败)); } } }这个控制器的逻辑很清晰生成任务ID - 调用OCR服务 - 异步保存结果 - 立即返回响应。用户不用等待数据存到数据库体验更好。3.4 添加接口限流为了防止某个用户疯狂调用我们的接口或者突发流量打垮服务加一个简单的限流很有必要。这里用Guava的RateLimiter。创建一个RateLimitService.javapackage com.yourproject.service; import com.google.common.util.concurrent.RateLimiter; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; Service Slf4j public class RateLimitService { private RateLimiter rateLimiter; PostConstruct public void init() { // 每秒允许10个请求可以根据实际压力调整 this.rateLimiter RateLimiter.create(10.0); log.info(接口限流器初始化完成速率: 10 QPS); } /** * 尝试获取令牌如果获取不到则立即返回false非阻塞 * return 是否允许通过 */ public boolean tryAcquire() { return rateLimiter.tryAcquire(); } /** * 获取令牌如果获取不到会阻塞等待谨慎使用避免线程堆积 */ public void acquire() { rateLimiter.acquire(); } }然后在控制器里对识别接口应用限流。修改OcrController的recognizeImage方法在开头添加PostMapping(/recognize) public MonoResponseEntity? recognizeImage(RequestParam(file) MultipartFile file) { // 限流检查 if (!rateLimitService.tryAcquire()) { log.warn(接口触发限流拒绝请求); return Mono.just(ResponseEntity.status(429).body(请求过于频繁请稍后再试)); // 429 Too Many Requests } // ... 原有的其他代码 ... }记得在控制器里注入RateLimitService。3.5 添加日志与监控日志是排查问题的眼睛。我们已经用Slf4j注解在关键地方打了日志。为了更好监控可以增加一个切面AOP来统一记录每个OCR请求的耗时和状态。首先添加Spring AOP依赖如果创建项目时没选dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-aop/artifactId /dependency然后创建一个切面类package com.yourproject.aspect; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.Arrays; Aspect Component Slf4j public class OcrLoggingAspect { Around(execution(* com.yourproject.controller.OcrController.*(..))) public Object logApiCall(ProceedingJoinPoint joinPoint) throws Throwable { long startTime System.currentTimeMillis(); String methodName joinPoint.getSignature().getName(); Object[] args joinPoint.getArgs(); // 获取请求信息如果有 String clientIp N/A; try { ServletRequestAttributes attributes (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes ! null) { HttpServletRequest request attributes.getRequest(); clientIp request.getRemoteAddr(); } } catch (Exception ignored) {} log.info(OCR API调用开始 - 方法: {}, 客户端IP: {}, 参数: {}, methodName, clientIp, Arrays.toString(args)); Object result; try { result joinPoint.proceed(); // 执行原方法 long elapsedTime System.currentTimeMillis() - startTime; log.info(OCR API调用成功 - 方法: {}, 耗时: {}ms, methodName, elapsedTime); } catch (Throwable e) { long elapsedTime System.currentTimeMillis() - startTime; log.error(OCR API调用异常 - 方法: {}, 耗时: {}ms, 异常: {}, methodName, elapsedTime, e.getMessage(), e); throw e; // 重新抛出异常 } return result; } }这个切面会自动拦截OcrController里所有的方法记录下谁、什么时候、调用了什么接口、花了多长时间、成功还是失败。线上出问题时查日志会非常方便。4. 快速上手与测试代码写完了我们来跑一下看看效果。启动应用运行你的SpringBoot主类通常是XxxApplication.java。准备测试图片找一张包含清晰文字的图片比如一张截图或者拍的名片。使用工具测试打开Postman或者任何你喜欢的API测试工具。创建一个POST请求地址是http://localhost:8080/api/ocr/recognize。选择form-data格式添加一个key为file和代码中RequestParam(file)对应类型为File的参数上传你的测试图片。点击发送。查看结果如果成功你会立刻收到类似“识别任务已提交任务ID: xxxxxxxx-xxxx-xxxx...”的响应。查看应用控制台日志应该能看到“调用GLM-OCR API”、“异步保存OCR结果成功”等日志。去MySQL数据库里查一下ocr_result表应该能看到一条新记录recognized_text字段里就是识别出的文字。测试限流快速连续发送多个请求大概在第11个请求左右因为我们设置了10 QPS你应该会收到429状态码和“请求过于频繁”的提示。5. 实用技巧与问题排查在实际集成过程中你可能会遇到一些小问题。这里分享几个常见的坑和解决办法。OCR接口返回格式不符这是最常见的问题。GlmOcrService里解析JSON的代码 (rootNode.path(data).path(text)) 必须根据GLM-OCR接口实际的返回结构来修改。最好的办法是先用Postman单独调一下他们的接口看看返回的JSON长什么样然后调整解析逻辑。文件上传大小限制如果你上传的图片太大Spring可能会报错。记得检查application.yml里设置的max-file-size和max-request-size是否足够。网络超时如果OCR服务响应慢可能会超时。可以适当调大glm.ocr.timeout的值比如改成3000030秒。数据库连接问题确保MySQL服务已启动并且application.yml里的数据库连接信息url, username, password是正确的。异步任务不执行检查EnableAsync注解是否加在了配置类上以及Async注解的方法是否在同一个类内部调用Spring AOP代理导致的坑内部调用不会走代理异步失效。最好把异步方法放在另一个Service类中调用。限流不生效检查RateLimitService是否被正确注入到Controller以及tryAcquire()的调用位置是否在方法的最开始。6. 总结走完这一整套流程你应该已经成功地把GLM-OCR服务集成到你的SpringBoot项目里了。我们不仅完成了最基本的图片上传和文字识别还设计了异步存储来提升接口响应速度加了限流保护服务并通过AOP统一了日志监控。这套东西虽然不算复杂但已经具备了在生产环境运行的基本骨架。实际用起来你会发现最关键的一步其实是调试OCR接口的调用和响应解析因为不同服务商的API设计可能差别很大。只要把这部分调通了后面的数据库存储、异步处理都是SpringBoot的常规操作套用模板就行。这个方案还有不少可以优化的地方比如引入消息队列如RabbitMQ来更可靠地处理异步任务或者把识别结果缓存到Redis里加快查询速度。你可以根据自己项目的实际需求和流量情况慢慢往上加。希望这篇教程能帮你省点时间如果遇到其他问题多看看日志思路清晰地去排查总能解决的。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

相关新闻

3步解决魔兽争霸III现代系统兼容难题:面向经典游戏玩家的开源工具

3步解决魔兽争霸III现代系统兼容难题:面向经典游戏玩家的开源工具

3步解决魔兽争霸III现代系统兼容难题:面向经典游戏玩家的开源工具 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 问题引入:当…

2026/7/4 5:05:56 阅读更多 →
深入解析CherryUSB中的XHCI驱动实现与优化策略

深入解析CherryUSB中的XHCI驱动实现与优化策略

1. 初识CherryUSB与XHCI:嵌入式USB开发的“瑞士军刀” 如果你在嵌入式领域摸爬滚打过,肯定遇到过这样的场景:项目需要一个USB主机功能,比如读取U盘、连接键盘鼠标,或者通过USB网卡上网。这时候,你可能会去翻…

2026/7/3 23:48:29 阅读更多 →
Python pip安装报错:fatal error in launcher的终极解决方案

Python pip安装报错:fatal error in launcher的终极解决方案

1. 这个烦人的错误到底是怎么回事? 相信很多Python开发者,尤其是刚入门不久的朋友,都遇到过这个让人瞬间血压升高的报错:fatal error in launcher: unable to create process using。你正满心欢喜地想装个新库,准备大…

2026/5/17 7:46:05 阅读更多 →

最新新闻

oyunfor土区礼品卡购买教程及踩坑记录

oyunfor土区礼品卡购买教程及踩坑记录

前置条件🔮我用的美丽国 chorme浏览器(edge没成功) 可安装翻译插件 招商银行万事达(研究生优选) 网络连接设置 属性里取消勾选ipv6协议(买好再改回来)1.注册账号需🔮 用的QQ邮箱,Gmail邮箱收不到验证码 其他信息正常填写,号码862.…

2026/7/5 15:10:30 阅读更多 →
教师资格证认定

教师资格证认定

前言 认定是获取教师资格证的第三个环节,也是最后一个环节。认定通过之后,即可取得教师资格证。 认定时间和认定条件 认定时间 每年的教师资格认定工作有上半年和下半年两个批次。不同于笔试和面试,教师资格证认定的时间并非全国统一。认定的…

2026/7/5 15:10:29 阅读更多 →
NTP算法实现客户端与服务器时间同步

NTP算法实现客户端与服务器时间同步

基于四时间戳(T1~T4)的NTP级时间同步机制:通过分离 Client→Server 与 Server→Client 传输时间计算延迟时间,通过记录请求发送(T1)、服务端接收(T2)/回复(T3)、客户端接收(T4)四个时间戳,利用对称消除公式 Offset (T…

2026/7/5 15:10:29 阅读更多 →
新e选烤火罩异味[主里料] GB 18401—2010 6.7 判定符合检测标准与测试条件

新e选烤火罩异味[主里料] GB 18401—2010 6.7 判定符合检测标准与测试条件

国标要求:纺织品无异味;恒温密闭环境专业嗅辨。实测结果内里衬料无任何化工、塑胶、胶水异味,嗅辨合格。家用实用优势部分烤火罩外层做除味处理,但内里廉价衬布残留浓烈胶水味,高温烘烤后异味从内部散发。新e选烤火罩里…

2026/7/5 15:08:29 阅读更多 →
STM32与EEPROM数据存储可靠性设计与优化实践

STM32与EEPROM数据存储可靠性设计与优化实践

1. 项目背景与核心需求在嵌入式系统开发中,数据存储的可靠性往往决定了整个系统的稳定性。我最近为一个工业传感器网络项目设计数据存储方案时,深刻体会到选择合适存储器件的重要性。这个网络需要持续记录环境参数,并在断电后仍能保存关键数据…

2026/7/5 15:06:29 阅读更多 →
如何用ConvertToUTF8解决Sublime Text中文乱码:3步快速上手指南

如何用ConvertToUTF8解决Sublime Text中文乱码:3步快速上手指南

如何用ConvertToUTF8解决Sublime Text中文乱码:3步快速上手指南 【免费下载链接】ConvertToUTF8 A Sublime Text 2 & 3 plugin for editing and saving files encoded in GBK, BIG5, EUC-KR, EUC-JP, Shift_JIS, etc. 项目地址: https://gitcode.com/gh_mirro…

2026/7/5 15:02:28 阅读更多 →

日新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻