Springboot整合百度人脸识别功能实现注册和登录
超详细多种人脸识别教程请参考CSDN中CodeDevMaster大佬的教程链接如下Java借助百度云人脸识别实现人脸注册、登录功能的完整示例_百度api 视频流人脸识别 java-CSDN博客本文档的百度AI人脸识别主要用于人脸登录等功能类似于手机上的面容解锁需要上传到百度AI接口两张照片进行校验如果需要类似腾讯的实名认证人脸识别真实姓名身份证号人脸的功能请参考上面的文档且需要在百度AI进行企业认证调用V4接口。据百度AI工程师说之前的老用户可以使用V3接口的实名认证人脸识别现在的新用户都需要进行企业认证调用V4接口。详细操作请参考百度AI人脸识别官方文档和错误码文档官方API人脸对比 - 人脸识别_人脸检测_人脸对比_人脸搜索_活体检测_百度智能云 (baidu.com)官方错误码文档人脸识别人脸检测人脸对比人脸搜索活体检测_百度智能云 (baidu.com)项目压缩包链接https://download.csdn.net/download/2301_79357346/89241774如文档有错误请与我联系谢谢准备工作登录百度智能云控制台https://console.bce.baidu.com/开通人脸识别选择人脸识别项创建人脸识别应用人脸识别接口默认全部选择也可以选择添加其他接口。得到应用ID、API KEY、Secret Key添加依赖dependencies !--单元测试启动器-- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId /dependency !--web启动器依赖(springMVC)-- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !--druid-SpringBoot启动器依赖-- dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.1.10/version /dependency !--JDBC启动器依赖-- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId /dependency !-- MyBatis-Plus-- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.2.0/version /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.2.0/version /dependency !--mysql驱动-- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.16/version /dependency !--spring boot actuator依赖-- !--实时监控数据以前从来没使过 可不加-- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-actuator/artifactId /dependency !--编码(辅助)工具包-- !-- 注不加可能会报错加上就好使了 它提供了大量用于处理字符串、日期的实用方法以及其它一些如集合、数组、概率和随机等类库。-- dependency groupIdorg.apache.commons/groupId artifactIdcommons-lang3/artifactId /dependency !-- 分布式上传文件(静态资源)-- dependency groupIdcom.aliyun.oss/groupId artifactIdaliyun-sdk-oss/artifactId version3.15.1/version /dependency !--百度AI-- dependency groupIdcom.baidu.aip/groupId artifactIdjava-sdk/artifactId version4.9.0/version /dependency /dependencies build plugins !-- 可不加-- !--spring boot maven插件 , 可以将项目运行依赖的jar包打到我们的项目中-- plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin /plugins /build项目结构参考如下数据库参考如下用户表要保证username用户名账号不能重复创建BaiduAiConfigpackage com.baidu.config; import org.springframework.context.annotation.Configuration; Configuration public class BaiduAiConfig { public static final String AppId 你的APPID; public static final String AK 你的API Key; public static final String SK 你的Secret Key; }我最初是在application.yml配置文件中写AppId、AK、SK但是类中获取不到所以才这么写的创建OssUtil图片上传工具类这里图片是保存到阿里云的OSS服务器中了如果你没有阿里云的OSS服务器可以直接去阿里云官网免费注册OSS文件上传详细教程请参考CSDN中liaozk_c大佬的教程阿里云存储OSS文件上传详细教程_阿里oss文件上传-CSDN博客package com.baidu.util; import com.aliyun.oss.ClientConfiguration; import com.aliyun.oss.OSSClient; import com.aliyun.oss.common.auth.DefaultCredentialProvider; import com.aliyun.oss.model.CannedAccessControlList; import com.aliyun.oss.model.PutObjectResult; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; Component public class OssUtil { private static String endPoint ; // oss域名 private static String accessKeyId ; // accessKeyId private static String accessKeySecret ; // accessKeySecret private static String bucketName ; // 桶名称 private static String fileDir /img; // 当前文件所属文件夹(就是你想给文件传到那个文件夹下面) //log日志对象 static Log log LogFactory.getLog(OssUtil.class); /** * oss 工具客户端 */ private static OSSClient ossClient null; /** * 上传文件至阿里云 OSS * param file 待上传文件 * 返回访问的全路径 */ public static String uploadFileToOss(MultipartFile file) { // 初始化oss initOSS(endPoint, accessKeyId, accessKeySecret); String visitUrl null; try { // 获取文件名 String orgName file.getOriginalFilename(); if (StringUtils.isEmpty(orgName)) { orgName file.getName(); } orgName getFileName(orgName); //上传后的文件名 进行修饰 String fileRelName fileDir orgName.substring(0, orgName.lastIndexOf(.)) _ System.currentTimeMillis() orgName.substring(orgName.indexOf(.)); // 上传至oss PutObjectResult result ossClient.putObject(bucketName, fileRelName, file.getInputStream()); if (result ! null) { log.info(------OSS文件上传成功------); } // 拼接访问路径 visitUrl https:// bucketName . endPoint / fileRelName; System.out.println(visit url : visitUrl); } catch (IOException e) { log.error(e.getMessage(), e); return null; } return visitUrl; } /** * 删除文件 * param fileName */ public static void deleteFileToOss(String fileName) { // 初始化oss initOSS(endPoint, accessKeyId, accessKeySecret); ossClient.deleteObject(bucketName, fileName); } /** * 初始化 oss 客户端 * return */ private static OSSClient initOSS(String endpoint, String accessKeyId, String accessKeySecret) { if (ossClient null) { synchronized (OSSClient.class) { if (ossClient null) { ossClient new OSSClient(endpoint, new DefaultCredentialProvider(accessKeyId, accessKeySecret), new ClientConfiguration()); // 设置权限(公开读) ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead); } } } return ossClient; } /** * 判断文件名是否带盘符重新处理 * param fileName * return */ public static String getFileName(String fileName){ //判断是否带有盘符信息 // Check for Unix-style path int unixSep fileName.lastIndexOf(/); // Check for Windows-style path int winSep fileName.lastIndexOf(\\); // Cut off at latest possible point int pos (winSep unixSep ? winSep : unixSep); if (pos ! -1) { // Any sort of path separator found... fileName fileName.substring(pos 1); } //替换上传文件名字的特殊字符 fileName fileName.replace(, ).replace(,, ).replace(, ).replace(#, ); return fileName; } public static String getEndPoint() { return endPoint; } public static void setEndPoint(String endPoint) { OssUtil.endPoint endPoint; } public static String getAccessKeyId() { return accessKeyId; } public static void setAccessKeyId(String accessKeyId) { OssUtil.accessKeyId accessKeyId; } public static String getAccessKeySecret() { return accessKeySecret; } public static void setAccessKeySecret(String accessKeySecret) { OssUtil.accessKeySecret accessKeySecret; } public static String getBucketName() { return bucketName; } public static void setBucketName(String bucketName) { OssUtil.bucketName bucketName; } public static String getFileDir() { return fileDir; } public static void setFileDir(String fileDir) { OssUtil.fileDir fileDir; } public static OSSClient getOssClient() { return ossClient; } public static void setOssClient(OSSClient ossClient) { OssUtil.ossClient ossClient; } }创建Base64Util该类主要是负责把前端传回来的MultipartFile类型的人脸识别图片文件转换为百度AI需要的base64格式package com.baidu.util; import org.springframework.web.multipart.MultipartFile; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Base64; /** * Base64 工具类 */ public class Base64Util { private static final char last2byte (char) Integer.parseInt(00000011, 2); private static final char last4byte (char) Integer.parseInt(00001111, 2); private static final char last6byte (char) Integer.parseInt(00111111, 2); private static final char lead6byte (char) Integer.parseInt(11111100, 2); private static final char lead4byte (char) Integer.parseInt(11110000, 2); private static final char lead2byte (char) Integer.parseInt(11000000, 2); private static final char[] encodeTable new char[]{A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, , /}; public Base64Util() { } public static String multipartFileToBase64(MultipartFile file) throws IOException { InputStream inputStream file.getInputStream(); ByteArrayOutputStream byteArrayOutputStream new ByteArrayOutputStream(); int bytesRead; int bufferSize 10 * 1024 * 1024; byte[] buffer new byte[bufferSize]; // 可以根据需要调整缓冲区大小 while ((bytesRead inputStream.read(buffer)) ! -1) { byteArrayOutputStream.write(buffer, 0, bytesRead); } byte[] bytes byteArrayOutputStream.toByteArray(); String base64String Base64.getEncoder().encodeToString(bytes); // 不需要显式关闭 inputStream因为 MultipartFile 的实现会负责关闭它 // byteArrayOutputStream.close(); // 如果需要可以在这里关闭 ByteArrayOutputStream return base64String; } public static String encode(byte[] from) { StringBuilder to new StringBuilder((int) ((double) from.length * 1.34D) 3); int num 0; char currentByte 0; int i; for (i 0; i from.length; i) { for (num % 8; num 8; num 6) { switch (num) { case 0: currentByte (char) (from[i] lead6byte); currentByte (char) (currentByte 2); case 1: case 3: case 5: default: break; case 2: currentByte (char) (from[i] last6byte); break; case 4: currentByte (char) (from[i] last4byte); currentByte (char) (currentByte 2); if (i 1 from.length) { currentByte (char) (currentByte | (from[i 1] lead2byte) 6); } break; case 6: currentByte (char) (from[i] last2byte); currentByte (char) (currentByte 4); if (i 1 from.length) { currentByte (char) (currentByte | (from[i 1] lead4byte) 4); } } to.append(encodeTable[currentByte]); } } if (to.length() % 4 ! 0) { for (i 4 - to.length() % 4; i 0; --i) { to.append(); } } return to.toString(); } }创建CodeCompentspackage com.baidu.compents; public class CodeCompents { public final static String baidu_ai_imageType BASE64; public final static String baidu_ai_groupId groupId; }创建UserBaiduAIController登录接口需要传入用户名账号和登录时的图片然后获取数据库中注册的人脸识别照片的URL传到百度AI进行比对如果数据库中没有该用户的人脸识别照片的URL则为该用户没有注册人脸识别直接返回请先注册人脸识别注册接口需要传入用户名账号和注册的人脸图片然后将人脸识别的照片上传到阿里云的OSS服务器并获取保存的URL然后将URL给到用户类里对应的属性中再调用修改方法对数据库中的信息修改将注册的人脸识别图片URL保存到数据库中package com.baidu.controller; import com.baidu.aip.face.AipFace; import com.baidu.aip.face.MatchRequest; import com.baidu.compents.CodeCompents; import com.baidu.config.BaiduAiConfig; import com.baidu.pojo.UserBaiduai; import com.baidu.service.UserBaiduAIService; import com.baidu.util.Base64Util; import com.baidu.util.OssUtil; import org.apache.commons.lang3.ObjectUtils; import org.json.JSONException; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; RestController RequestMapping(/baiduAI) public class UserBaiduAIController { Autowired private UserBaiduAIService userBaiduAIService; /** * 账号人脸校验 * param userName * param file * throws Exception */ PostMapping(/loginBaiduAi) public void loginBaiduAi(String userName, MultipartFile file) throws Exception { // 传入appId、apiKey、secretkey。创建Java代码和百度云交互的Client对象 AipFace client new AipFace(BaiduAiConfig.AppId, BaiduAiConfig.AK, BaiduAiConfig.SK); // 登录图片 // MultipartFile类型转换Base64字符串格式 String loginImageBase64 Base64Util.multipartFileToBase64(file); // 根据用户名获取用户信息 UserBaiduai one userBaiduAIService.findByName(userName); /* 判断该用户是否注册了人脸 如果没有注册则不进行校验 如果注册了则进行校验 */ if (!ObjectUtils.isEmpty(one.getPhoto())){ // 用户注册的人脸的照片存储路径 String comparedImageUrl one.getPhoto(); /* 传入参数进行校验 返回值为两张照片的相似度 */ Double faceComparison faceComparison(client, loginImageBase64, comparedImageUrl); if (faceComparison 85) { System.out.println(one.getUsername()); System.out.println(人脸识别登录成功); } else { System.out.println(人脸识别登录失败); } }else { System.out.println(请先录入人脸信息); } } PostMapping(registerBaiduAi) public void registerBaiduAi(String userName,MultipartFile file) throws IOException, JSONException { // 传入appId、apiKey、secretkey。创建Java代码和百度云交互的Client对象 AipFace client new AipFace(BaiduAiConfig.AppId, BaiduAiConfig.AK, BaiduAiConfig.SK); // 根据用户名获取用户信息 UserBaiduai one userBaiduAIService.findByName(userName); // 判断用户是否注册过人脸识别 if(!ObjectUtils.isEmpty(one.getPhoto())){ // 如果有则先删除原来注册的人脸照片 // 假设图片URL是https://canghai0190.oss-cn-beijing.aliyuncs.com/img/1714270552688.png // 那么我们要截取com/后面的文件路径名称传入方法进行删除 int index one.getPhoto().indexOf(com/); String fileName null; if (index ! -1) { fileName one.getPhoto().substring(index 4); // 截取 com/ 后面的内容 } else { fileName ; } System.out.println(fileName); OssUtil.deleteFileToOss(fileName); } // MultipartFile类型转换Base64字符串格式 String registerImageBase64 Base64Util.multipartFileToBase64(file); // 传入可选参数调用接口 HashMapString, String options new HashMapString, String(); options.put(user_info, users info); options.put(quality_control, NORMAL); options.put(liveness_control, LOW); options.put(action_type, REPLACE); /* 调用api方法完成人脸注册 image 图片的url或者base64字符串 imageType 图片形式URLBASE64 groupId 组Id固定一个字符串 userId 用户Id options hashMap基本参数配置 */ JSONObject res client.addUser(registerImageBase64, CodeCompents.baidu_ai_imageType, CodeCompents.baidu_ai_groupId, String.valueOf(userName), options); if (res.getInt(error_code)0){ //上传人脸识别图片到oss String url OssUtil.uploadFileToOss(file); //将人脸识别信息和用户信息绑定存入数据库 UserBaiduai userBaiduai userBaiduAIService.findByName(userName); userBaiduai.setPhoto(url); userBaiduAIService.update(userBaiduai); //更新redis中的用户信息 // updateUser(hmsUser); System.out.println(人脸注册成功); }else { System.out.println(人脸注册失败); } System.out.println(res.toString(2)); } static Double faceComparison(AipFace client, String loginImageBase64, String comparedImageUrl) throws Exception { // 将图片的URL传递给百度API MatchRequest req2 new MatchRequest(comparedImageUrl, URL); // 将前端传过来的图片传递给百度API MatchRequest req1 new MatchRequest(loginImageBase64, CodeCompents.baidu_ai_imageType); // 讲MatchRequest信息存入list集合中 ArrayListMatchRequest requests new ArrayList(); requests.add(req1); requests.add(req2); // 进行人脸比对 返回值是json串 JSONObject match client.match(requests); System.out.println(match.toString(2)); // 返回两张照片的相似度 return match.getJSONObject(result).getDouble(score); } }测试由于本人vue会的实在不多所以前端没有写出来想要页面的请参考我最上面放的CodeDevMaster大佬的链接教程最后面有vue前端的教程为了测试我这边就使用Postman进行测试需要的参数有params中userName参数body中名为file的file类型的一个照片文件注册接口的测试结果登录接口的测试结果登录接口人脸正确的结果登录接口人脸识别的接口怎么判断两张照片是否为同一个人大家应该可以看到我上面两次测试都用红框框起来的score这个值这个值的意思是传入百度AI的登录的人脸照片和数据库中注册的人脸照片的匹配值匹配值越高则大概率是同一个人匹配值越低则说明越不可能是同一个人然后我们只需要根据这个值进行判断即可一般是相似度大于等于85即可判断为同一个人小于85则判断为不是同一个人返回的JSON中各个属性是什么意思score 人脸相似度得分 face_list 人脸信息列表 face_token 人脸的唯一标志 log_id 是请求标识码随机数唯一 location 是人脸在图片中的位置 error_code 错误码 error_msg 误描述信息帮助理解和解决发生的错误

相关新闻

JAVA练习326- 下一个排列

JAVA练习326- 下一个排列

题目概览 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如,arr [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式…

2026/9/3 18:05:41 阅读更多 →
电流镜电路分析仿真电路结果与分析

电流镜电路分析仿真电路结果与分析

电流镜电路 目录电流镜电路电流镜电路分析仿真电路结果与分析实际电路搭建为什么不读万用表电流档位?电流镜电路分析仿真电路结果与分析 电流镜电路是一种电流复制技术,利用三极管的电流特性,选取两同类型的三极管(β\betaβ相同)&#xff0c…

2026/8/31 8:52:47 阅读更多 →
Django毕业设计-基于 Django 的鲜花线上销售与配送管理系统 个性化鲜花定制电商平台的设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)

Django毕业设计-基于 Django 的鲜花线上销售与配送管理系统 个性化鲜花定制电商平台的设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/8/26 0:08:57 阅读更多 →

最新新闻

试压包快速生成软件V2.10实战:焊口台账到压力试验资料一键搞定

试压包快速生成软件V2.10实战:焊口台账到压力试验资料一键搞定

简介:试压包快速生成软件V2.10(注册版,非源码)是一款面向管道工程、无损检测及施工单位技术人员的专业工具,核心价值在于将试压包文档从手工编制转为自动批量生成,显著提升工作效率并降低差错率。软件支持管…

2026/9/3 18:05:50 阅读更多 →
Camera2实战:从架构到填坑的完整指南

Camera2实战:从架构到填坑的完整指南

简介:Camera2Demo是一份面向Android开发者的Camera2 API封装示例,专门解决原生相机接口初始化复杂、业务耦合度高的问题。它把预览、拍照、保存等操作从Activity中剥离,通过统一封装降低API使用门槛,让开发者能够更专注于界面与业…

2026/9/3 18:05:50 阅读更多 →
MFC自绘CListCtrl完美实现:失焦保持高亮、斑马纹与自定义行高

MFC自绘CListCtrl完美实现:失焦保持高亮、斑马纹与自定义行高

简介:这是一份面向MFC开发者的自绘控件参考源码,重点演示如何通过重载OnDrawItem与OnDrawColumnHeader实现CListCtrl及CHeaderCtrl的完全自定义绘制,包括网格线、列表项样式与列头外观,并处理非Item区域的背景绘制,适合…

2026/9/3 18:05:50 阅读更多 →
基于S7-200 SMART的三拖三恒压供水系统设计与实现

基于S7-200 SMART的三拖三恒压供水系统设计与实现

简介:这是一套面向自动化工程师与工业现场调试人员的西门子200smart恒压供水三拖三程序资源,主要解决三台水泵和三台变频器一对一控制时的启停切换、运行稳定性问题;系统支持三台水泵循环软启、定时轮换,并采用PLC内部PID运算实现…

2026/9/3 18:05:50 阅读更多 →
网页FPS准星切换:用CSS变量实现狙击枪到步枪样式

网页FPS准星切换:用CSS变量实现狙击枪到步枪样式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/3 18:05:49 阅读更多 →
ROS语音识别实战:整合科大讯飞API与Python实现机器人听觉

ROS语音识别实战:整合科大讯飞API与Python实现机器人听觉

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/3 18:04:49 阅读更多 →

日新闻

AI智能体辅助JS逆向:从V8环境搭建到补环境实战

AI智能体辅助JS逆向:从V8环境搭建到补环境实战

先别急着点开,这不是劝退文,而是想讲清楚一件事:用 AI 做逆向值不值得学?如果要用,怎么搭一套“V8 环境 AI 智能体”来提升效率。最近逆向圈、爬虫圈都在聊 AI Agent、AST 工程逆向、JS 逆向这些词,很多新手…

2026/9/3 0:00:29 阅读更多 →
安卓设备通过修改机型信息解锁游戏高帧率:原理、操作与风险指南

安卓设备通过修改机型信息解锁游戏高帧率:原理、操作与风险指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/3 0:00:29 阅读更多 →
ARM版OpenJDK 11安装部署全攻略:下载、配置与避坑指南

ARM版OpenJDK 11安装部署全攻略:下载、配置与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/3 0:00:29 阅读更多 →

周新闻

备战数据库管理工程师校招:索引、事务、备份恢复核心考点解析

备战数据库管理工程师校招:索引、事务、备份恢复核心考点解析

每年校招季我都会接触不少准备数据库方向笔试的同学,看到最多的状态就是:简历上写着“熟悉 MySQL”“了解索引优化”,一碰到数据库管理工程师的笔试卷,却在索引、事务、锁、备份恢复这些题目上翻车。网易这套 2018 校园招聘数据库…

2026/9/3 4:22:22 阅读更多 →
数字电路时序基石:深入理解建立时间与保持时间

数字电路时序基石:深入理解建立时间与保持时间

1. 这不是“背公式”的事:时间参数到底在约束什么你翻过数字电路教材,一定见过这两个词:建立时间(Setup Time)和保持时间(Hold Time)。它们常被并列写在触发器(Flip-Flop&#xff09…

2026/9/3 4:22:01 阅读更多 →
蓝桥杯国赛超声波测距机:从单片机原理到嵌入式系统实战

蓝桥杯国赛超声波测距机:从单片机原理到嵌入式系统实战

1. 项目缘起:从赛题到超声波测距机的诞生第八届蓝桥杯单片机设计与开发国赛的题目,我至今记忆犹新。它没有直接给出一个花哨的名字,而是用“超声波测距机”这个朴实无华的功能描述,精准地勾勒出了考核的核心。对于当时备赛的我而言…

2026/9/3 4:22:59 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/3 4:17:49 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/3 4:18:56 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/3 4:21:44 阅读更多 →