ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

百度AI人脸识别考勤系统实战:从接口调优到Spring Boot落地

百度AI人脸识别考勤系统实战:从接口调优到Spring Boot落地 简介面向高校考勤信息化建设的一篇技术论文聚焦基于百度AI人脸识别的高校学生考勤系统设计与实现适合教学管理者、相关专业学生及系统开发者参考。资源为PDF格式共1个文件大小约864KB内容涵盖需求分析、数据库设计用户表、学生表、教师表、考勤记录表、请假申请表、系统三大核心模块学生、教师、管理员功能划分以及百度人脸识别API的调用步骤与关键代码。文中详细展示了管理员如何将学生证件照注册至人脸库、学生通过摄像头调用接口完成人脸比对打卡的完整链路并对请假提交与审核、考勤信息查询与修正等功能作了清晰的流程讲解可帮助读者快速理解人脸识别考勤系统的业务闭环。基于MVC模式的架构分析也体现了高内聚低耦合的设计思路对毕业设计、课程论文或实际项目开发具有直接借鉴价值。已有2221人学习浏览适合作为人脸识别应用方向的参考文献。 我最近刚把一个“百度AI人脸识别考勤系统”从论文设计落到了实际可运行的代码整个过程踩了不少坑也总结出一些值得说的经验。这篇就完整复盘一下从选型思路、系统架构到核心接口怎么调、数据库怎么设计再到底层那些“文档里不会写”的细节一次性讲清楚。项目本身不复杂核心就一句话用摄像头抓人脸调用百度AI开放平台的人脸识别接口完成身份比对再结合业务系统记录上下班时间、生成考勤报表。适合三类人看一是要做毕业设计或者课程项目的学生二是小企业里想用低成本方案替换指纹考勤机的开发者三是对接第三方API不太熟、想看看完整落地流程的后端工程师。先说结论这套方案的整体成本很低百度AI人脸识别有免费额度具体配额以官方最新说明为准个人开发或者小型团队完全可以零成本跑通核心流程。但前提是架构设计要对、接口参数要懂、异常情况要考虑全否则识别是能识别离“能用的考勤系统”还很远。1. 选型思路为什么是百度AI而不是自己训练模型任何一个考勤系统项目启动时第一个绕不开的问题就是人脸识别这块到底怎么实现我在立项时列过几个可选方向逐个排了一遍。OpenCV Haar Cascade或者DNN人脸检测属于纯本地方案优点是离线可用、不花钱缺点也很明显识别准确率受光照、角度影响非常大活体检测基本没法做拿张照片就能骗过去。稍微好一点的是用Dlib做特征提取但Dlib模型在亚洲人脸、侧脸、遮挡场景下的表现并不理想而且后期维护成本全在自己身上。ESP32-S3 CAM这类硬件方案我也看过适合做原型验证但算力有限跑轻量模型可以做严肃的考勤记录不太稳。最后选百度AI开放平台的人脸识别接口核心考虑是三个。第一是准确率百度的人脸检测和对比算法经过大规模数据训练在复杂场景下的鲁棒性明显优于自己用OpenCV拼出来的方案。第二是功能完整度它直接提供了人脸检测、人脸搜索、活体检测、人脸库管理这一整套能力不需要自己维护特征向量和比对逻辑。第三是接入成本HTTP API JSON返回Java、Python、PHP都能轻松对接文档完善而且有免费额度可以做原型验证。这里面有一个容易忽略的点就是这个项目的热词里提到了“黑群晖开启人脸识别补丁”“imageen人脸识别 delphi”这类需求它们的核心逻辑其实都一样就是调用外部人脸识别能力。自己训练模型的路线不是不能走但需要大量标注数据、GPU资源和持续调优对于一个考勤系统来说严重超配。人脸识别在这类业务里是“能力组件”不是“核心竞争力”选一个成熟平台把能力接进来把精力花在考勤业务逻辑上才是性价比最高的方式。提示如果项目对外发布或者商用务必确认百度AI开放平台最新的计费策略和调用配额。个人开发阶段和商用阶段成本模型差别很大。2. 系统整体设计从摄像头到考勤报表的完整链路2.1 三层架构怎么划分整个考勤系统我按标准的三个层次来设计各层职责单一后期维护和扩展都方便。表现层负责采集人脸图像、展示考勤记录和报表界面。这里的关键设备是USB摄像头或者网络摄像头开发阶段用笔记本自带的摄像头完全够用。采集到的图像以Base64编码传给后端这是所有对接方式里最通用的一种。业务逻辑层是整个系统的核心部署为一个Java Spring Boot后端服务负责接收前端传来的图像数据调用百度AI人脸识别接口完成身份比对根据比对结果执行打卡逻辑然后再把打卡记录写入数据库。同时这一层还负责处理异常情况比如人脸不匹配、图像质量不合格、用户未注册等。数据层就是数据库设计。我用MySQL存储员工信息、人脸注册记录、打卡记录和考勤规则。人脸特征本身不存储在本地而是存放在百度云的人脸库中本地库只保存百度返回的face_token。这个设计很多人一开始想不明白其实非常简单face_token就相当于百度服务器上那张人脸的“身份证号”每次识别时我只需要拿着现场采集的人脸去百度库里搜索得到匹配的face_token再去MySQL里反查这个token对应的是哪个员工。这里把流程拆开看就更清楚了。员工注册人脸时前端采集一张人脸照片上传到后端。后端调用百度的人脸注册接口将照片加入指定的人脸库group_id百度返回一个face_token。后端将face_token和员工工号存储在本地MySQL的face_mapping表中。打卡时前端采集一张现场人脸照片上传到后端。后端调用百度的人脸搜索接口带着照片和group_id去搜索百度返回匹配的face_token以及置信度分数。后端拿返回的face_token在MySQL中查找对应员工找到就记录一条打卡记录找不到就提示未注册。这套设计的好处在于人脸特征向量的生成、存储和比对全部由百度处理本地只关联业务信息既保证了识别精度又简化了实现复杂度。2.2 数据库表结构怎么设计数据库设计直接决定整个系统能不能撑住后续的功能扩展我把核心表结构和关键字段列一下。员工表主要存基础信息包括id、employee_no工号、name、department部门、position职位、photo_url可选的头像路径、create_time。工号在整个系统里是业务主键所有关联都通过它串联。人脸映射表是整个系统的关键表字段包括id、employee_no、face_token、group_id对应百度侧的组、status启用或停用、create_time。这里必须以employee_no加group_id做联合唯一索引防止同一员工在同一个组里重复注册。打卡记录表用来存每一次的打卡明细字段包括id、employee_no、check_time打卡时间、check_type上班卡或下班卡、face_score识别置信度、image_url现场照片可选用于争议追溯、create_time。这张表会越积越大建议定期归档。考勤规则表维护上下班时间和迟到早退判定参数比如morning_start、morning_end、afternoon_start、afternoon_end、late_minutes超过多少分钟算迟到等。不同部门如果有不同工时制这里做成可配置的就很有必要。考勤汇总表则是每日汇总结果比如date、employee_no、first_check_time当天第一次打卡、last_check_time当天最后一次打卡、status正常、迟到、早退、缺卡、work_hours工作时长。汇总表在月末导出工资数据时能省很多事。2.3 环境准备与工具清单开发环境这块列一个清单参考性很强。操作系统用Windows 10或11开发工具用IntelliJ IDEA后端框架Spring Boot 2.7.x语言Java 8或11数据库MySQL 5.7或8.0HTTP客户端使用Spring自带的RestTemplate或者OkHttp前端页面用Vue3或者纯HTML加JavaScript都行关键在于能拿到摄像头画面并转成Base64。百度AI开放平台侧需要的准备工作包括注册百度智能云账号创建人脸识别应用获取API Key和Secret Key然后在控制台创建一个空的人脸库群组这里的group_id后面会用到。整个人脸库的操作流程是创建应用后进入人脸识别控制台在人脸库管理页面新建一个群组系统会分配一个group_id之后所有注册和搜索的请求都要带着它。3. 核心接口对接Java Spring Boot完整实战3.1 拿到Access Token的几种方式与缓存策略调用百度AI接口的第一步是获取Access Token。这一步卡住了很多人不是因为文档难懂而是token的刷新机制没想清楚。我直接说结论token有效期是30天不建议每次请求都获取一次应当缓存起来在即将过期时再刷新。获取token的标准请求是HTTP GET访问https://aip.baidubce.com/oauth/2.0/token带上grant_typeclient_credentials、client_id你的API Key、client_secret你的Secret Key这三个参数返回结果里会有一个access_token字段。我在项目里是这么处理的把token存到Redis里设置28天的过期时间每次调用业务接口前先从Redis取取不到再重新获取并回填。如果没有Redis用一个带时间戳的静态变量缓存也可以单机场景完全够用。下面是获取token的核心代码直接可跑。Service public class BaiduAIService { private static final String TOKEN_URL https://aip.baidubce.com/oauth/2.0/token; private static final String CLIENT_ID 你的API Key; private static final String CLIENT_SECRET 你的Secret Key; private String accessToken; private long tokenExpireTime 0; public synchronized String getAccessToken() { if (accessToken ! null System.currentTimeMillis() tokenExpireTime) { return accessToken; } RestTemplate restTemplate new RestTemplate(); String url TOKEN_URL ?grant_typeclient_credentials client_id CLIENT_ID client_secret CLIENT_SECRET; MapString, Object response restTemplate.getForObject(url, Map.class); this.accessToken (String) response.get(access_token); long expiresIn ((Number) response.get(expires_in)).longValue(); this.tokenExpireTime System.currentTimeMillis() (expiresIn - 86400) * 1000; return this.accessToken; } }这段代码我加了提前一天的过期缓冲宁可少用一天也不要等到真过期了才发现。token失效的话所有识别接口会统一报错14001或110排查起来很被动。3.2 员工人脸注册接口实战注册的逻辑很好理解把一张已知是谁的人脸加入到百度的人脸库中。URL是https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add请求方式是POSTContent-Type为application/json。关键参数只有几个imageBase64字符串、image_typeBASE64、group_id群组标识、user_id用户标识、user_info附加信息可以存工号或姓名。这里有一个特别容易踩的坑user_id不能以数字开头也不能包含下划线以外的特殊符号。我一开始直接用员工工号“00123”当user_id结果接口直接返回错误后来改成“emp_00123”这种格式就正常了。注册成功后返回的face_token是这个用户在当前人脸库中的唯一标识但要注意同一个用户再次注册新的照片时百度会返回一个新的face_token这个token会替换库中的旧特征。所以在保存face_token到MySQL时要处理“重复注册”的情况先查库如果已存在就更新。public boolean registerFace(String employeeNo, String base64Image) { String url https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token getAccessToken(); HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); MapString, Object body new HashMap(); body.put(image, base64Image); body.put(image_type, BASE64); body.put(group_id, attendance_group); body.put(user_id, emp_ employeeNo); body.put(user_info, employeeNo); HttpEntityMapString, Object request new HttpEntity(body, headers); RestTemplate restTemplate new RestTemplate(); MapString, Object response restTemplate.postForObject(url, request, Map.class); MapString, Object result (MapString, Object) response.get(result); if (result ! null result.get(face_token) ! null) { String faceToken (String) result.get(face_token); // 更新本地映射表先删除旧记录再插入新记录 faceMapper.deleteByEmployeeNo(employeeNo); faceMapper.insert(employeeNo, faceToken, attendance_group); return true; } return false; }注意这段操作里我用了“先删再插”的策略因为同一个员工多次注册时百度侧旧的face_token已经没用了如果本地还留着后面搜索返回旧token就会查出重复记录或者员工信息对不上。3.3 人脸搜索比对接口实战核心打卡逻辑打卡识别是整个系统最关键的一环调用的接口是https://aip.baidubce.com/rest/2.0/face/v3/search请求方式和注册接口一致。参数中包含image现场人脸Base64、image_type、group_id_list可以传多个组逗号分隔、match_threshold匹配阈值通常80分以上算匹配。返回结果里会有一个score这就是两张人脸的相似度得分满分为100。实际测试下来同一个人的得分在90到100之间不同人的得分通常在60以下。阈值设置成80是一个比较稳妥的中间值太低了会把不相关的人放进来太高了又会因为角度、光线问题导致本人识别失败。搜索接口返回的user_id就是我注册时拼接好的“emp_”加工号直接解析就能得到员工编号。这样设计的好处是少一次数据库关联查询直接通过编程方式就能拿到业务主键。完整的匹配逻辑随便举一个示例如下所示。public String searchFace(String base64Image) { String url https://aip.baidubce.com/rest/2.0/face/v3/search?access_token getAccessToken(); HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); MapString, Object body new HashMap(); body.put(image, base64Image); body.put(image_type, BASE64); body.put(group_id_list, attendance_group); body.put(match_threshold, 80); HttpEntityMapString, Object request new HttpEntity(body, headers); RestTemplate restTemplate new RestTemplate(); MapString, Object response restTemplate.postForObject(url, request, Map.class); MapString, Object result (MapString, Object) response.get(result); if (result ! null) { ListMapString, Object userList (ListMapString, Object) result.get(user_list); if (userList ! null !userList.isEmpty()) { MapString, Object user userList.get(0); double score ((Number) user.get(score)).doubleValue(); if (score 80) { String userId (String) user.get(user_id); return userId.replace(emp_, ); } } } return null; }这个接口有几个隐含逻辑值得多说一嘴。user_list返回的是按分数降序排列的候选列表最多返回50个我们只取第一个就行。match_threshold设置的是硬门槛如果所有候选分数都低于这个值result里就只有一个fail_list而没有user_list直接把fail_reason展示给用户就行比如“未匹配到人脸”。3.4 活体检测和图像质量校验别忽略很多人对接百度AI人脸识别只用了搜索接口结果被一张打印照片轻松骗过。实际上百度的人脸识别接口在V3版本里已经把活体检测整合到了人脸检测接口中需要在识别前单独调用一次。做法是在打卡前先调用人脸检测接口https://aip.baidubce.com/rest/2.0/face/v3/detect在参数中带上face_fieldage,beauty,face_probability同时在请求体里设置face_liveness_score参数让返回结果包含活体分数。只有活体分数face_liveness_score大于某个阈值比如0.8才允许继续走人脸搜索。如果活体分数太低直接提示“请正对摄像头”或“请眨眼”。人脸检测接口还有几个质量参数对考勤系统影响很大。face_probability代表人脸概率低于0.5基本可以判定这张图里没有清晰的人脸。遮挡、模糊、光照异常这些信息也会在检测结果中体现。我在代码里加了简单判断如果face_probability低于0.6直接返回“人脸不清晰请重试”避免浪费一次搜索接口的调用次数。原因很简单搜索接口和检测接口虽然都计入API配额但搜索接口的结果在图片质量差时并不可靠与其让用户面对“对不起未匹配”的报错不如提前拦截并给出更准确的提示。3.5 打卡数据落库与状态判定拿到员工编号后打卡业务就变得很简单了。根据当前时间和考勤规则判断是打上班卡还是下班卡再判断是正常、迟到还是早退。这里有一个容易被忽视的问题早退怎么判定。早退必须等下班时间过了以后才能判断所以在记录打卡时不应该在第一次打卡时就生成最终的考勤状态而是把每次打卡当作明细记录然后在每日凌晨跑一个定时任务或者当天最后一次打卡时触发汇总计算。我这个项目采用的是“明细立即写、汇总定时算”的策略。打卡接口只负责把记录插入attendance_record表不更新考勤状态。每天凌晨1点定时任务扫描昨天的所有记录对每个员工取当天第一条和最后一条打卡结合考勤规则生成汇总。这样写的好处是逻辑清晰扩展性好比如后续想要支持“一天打4次卡”的工时制只需要改汇总逻辑不需要动打卡入口。4. 性能测试与QPS排查Jmeter压测实录系统中有一个环节是热词里多次提到的就是JMeter测试人脸识别接口。这个测试在正式上线前很有必要尤其是考勤这种场景上班前10分钟内会有大量并发请求涌入如果接口撑不住整个打卡体验就会崩掉。我用JMeter做了两轮测试。第一轮是单接口压测模拟50个线程同时调打卡接口循环10次总共500个请求。核心关注两个指标平均响应时间和错误率。500个请求全部成功平均响应时间在420毫秒左右这个数据在可接受范围内。第二轮加了Think Time来模拟真实操作间隔将线程数提到100各循环5次平均响应时间略微上升到680毫秒但整体错误率依然为0。需要提示的是上面的压测结果基于百度AI接口当时的响应表现仅作为参考。真实场景的瓶颈往往不在百度服务端而在应用服务器和数据库连接池。这里有两个优化点要提前处理好。一个是数据库连接池配置Spring Boot默认的HikariCP最大连接数是10并发高时会成为瓶颈。我在application.yml里将连接数提到50并在压测中确认没有连接超时。另一个是二进制图片的上传大小限制Spring Boot默认限制了请求体大小为1MB但一张高清摄像头照片往往在2MB左右必须在配置文件里把spring.servlet.multipart.max-request-size调整到10MB否则大图上传时会直接被Tomcat拒掉。有一点务必牢记人脸比对接口是昂贵的无论计费还是耗时不要在业务代码里做无意义的重复调用。比如注册接口里如果用户提交的图片和当前库中的图片一模一样可以通过face_token对比直接判定“重复注册”这样可以节省一次注册调用。打卡接口里如果前端传来的是模糊图片先用简单的图像尺寸、清晰度判断拦截掉也能节省百度API配额。5. 常见报错和乱码问题排查实录5.1 报错码速查表百度AI人脸识别接口返回的错误码比较规范把最常见的几个整理成表对接时可以直接对应排查。错误码含义排查方向14001Access Token失效或错误检查API Key和Secret Key、token是否缓存过期110Access Token过期重新获取token216201人脸库不存在先在控制台创建群组确认group_id拼写216401人脸质量不满足要求提升图片清晰度、调整光照、避免侧脸222202图片中没有人脸检查Base64是否正确、图片是否损坏216100图片格式错误确认图片为JPG、PNG等支持格式转码后再传216103图片大小超限单张图片控制在10MB以内223105活体检测未通过引导用户正视摄像头、眨眼或张嘴5.2 图片怎么转Base64才不会踩坑前端传上来的是文件流后端要转成Base64。这里有一个经典的坑直接使用原生Base64编码时可能包含换行符导致JSON解析失败。Java的处理方式很简单在转换成字符串后调用replaceAll(\r|\n, )把所有换行符去掉。另外在传给百度接口时要注意Base64字符串前不应带有data:image/jpeg;base64,这样的前缀百度要求的是纯Base64字符串。如果前端已经加了前缀后端要做一次截断处理。这里给出通用的代码片段public static String extractBase64(String imageData) { if (imageData.contains(,)) { return imageData.substring(imageData.indexOf(,) 1).replaceAll(\\r|\\n, ); } return imageData.replaceAll(\\r|\\n, ); }5.3 延迟和超时问题我在实际测试中遇到过一个情况打卡接口偶尔会超过3秒才返回。排查后发现两个因素。一是摄像头分辨率设置太高一张照片达到了5MB上传和Base64转码时间过长。解决办法是在前端控制摄像头采集分辨率设为1280x720足够用于人脸识别同时压缩输出图片质量。二是RestTemplate默认没有设置超时时间对方接口卡顿时整个请求线程会一直挂着。解决方法是自定义RestTemplate连接超时设为3秒读取超时设为5秒超过后直接提示用户“网络超时请重试”避免界面假死。Bean public RestTemplate restTemplate() { SimpleClientHttpRequestFactory factory new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(3000); factory.setReadTimeout(5000); return new RestTemplate(factory); }5.4 多摄像头设备同时打卡的处理如果公司考勤点不止一个比如前台一个、侧门一个每台设备都要独立打卡。这里的并发安全问题需要注意。我最初实现时打卡接口里先查数据库判断员工是否已经打过上班卡再决定是否插入记录结果在并发测试下出现了重复插入。后来改成数据库唯一索引的方式对employee_no和check_date加联合唯一索引打卡时先插入如果插入报错说明已经打过卡了直接返回“重复打卡”。这种方式比加分布式锁简单得多也更可靠。6. 前端摄像头调用细节GetUserMedia完整示例整个系统不能缺少前端这一环这里把摄像头采集页面的核心代码贴出来方便直接复用。GetUserMedia是浏览器原生的API可以获取摄像头视频流抓取当前帧绘制到Canvas再转成Base64传给后端。!DOCTYPE html html langzh-CN head meta charsetUTF-8 title人脸考勤打卡/title /head body video idvideo width600 height400 autoplay/video button idshootBtn拍照打卡/button canvas idcanvas styledisplay:none;/canvas script const video document.getElementById(video); const canvas document.getElementById(canvas); const context canvas.getContext(2d); async function initCamera() { const stream await navigator.mediaDevices.getUserMedia({ video: { width: 1280, height: 720, facingMode: user } }); video.srcObject stream; } document.getElementById(shootBtn).onclick function() { canvas.width video.videoWidth; canvas.height video.videoHeight; context.drawImage(video, 0, 0, canvas.width, canvas.height); const base64Data canvas.toDataURL(image/jpeg, 0.8).split(,)[1]; sendToServer(base64Data); }; async function sendToServer(base64Data) { const response await fetch(/api/attendance/check, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ image: base64Data }) }); const result await response.json(); alert(result.message); } initCamera(); /script /body /html这里有几个细节值得强调。videos配置里设置facingMode为user确保使用的是前置摄像头适合考勤机模式。拍照后canvas转图片时用toDataURL(image/jpeg, 0.8)第二个参数是压缩质量0.8的压缩比在图片大小和识别精度之间比较平衡。如果图像质量太差导致识别失败可以适当调高质量参数到0.9。此外GetUserMedia在HTTP非安全环境下是不可用的本地开发可以用localhost正式部署必须使用HTTPS否则摄像头会被浏览器拦截。这一点在局域网内部署考勤系统时很容易踩坑。7. 关于考勤系统后续扩展的几个方向我做这套系统时其实还考虑过几个后续可以延展的方向简单提一下方便读者按需扩展。第一个方向是钉钉或企业微信的集成。现在很多企业的考勤记录最终要汇总到OA或者IM工具里。可以在打卡成功时通过钉钉机器人Webhook发送一条消息通知或者在月末自动生成考勤报表推送给人资。实现思路并不复杂就是在打卡接口里异步调用Webhook接口。第二个方向是考勤数据可视化。MySQL里已经存了完整的打卡明细和汇总数据后续可以直接接一个ECharts或者Grafana展示每个部门的出勤率、迟到趋势、加班时长分布。这些数据对管理者来说比单个打卡记录有价值得多。第三个方向是多人同时识别。百度AI接口原生支持一张照片中检测多张人脸搜索接口会返回每个检测到的人脸对应的匹配结果。这样可以在同一个摄像头画面里同时为多人完成打卡技术上完全可行只需要在前端发起一次拍照后端循环处理多个人脸的匹配结果。需要注意的是这种场景对百度接口配额消耗较大且要处理好“同一个人同时出现在画面中只记一次卡”的逻辑。第四个方向在热词里也出现过就是门禁联动。将考勤成功信号输出给门禁控制器识别通过后自动开门。这个需要硬件配合通常通过串口或者继电器控制电磁锁。软件层只需在打卡成功后调用一个硬件控制接口逻辑不复杂但需要对硬件通信协议有一定了解。8. 写在最后一整套走下来我真实的体会我做完这套系统时最大的感受是人脸识别考勤的难点根本不在“识别”本身百度AI把最难的算法部分已经封装得很完善了真正决定项目成败的反而是那些业务细节token过期如何提前规避图片质量太差如何提示用户重复打卡如何防止并发大了数据库怎么抗住摄像头权限在HTTPS下如何保证。如果你是从零开始做类似项目我建议的落地顺序是先用Postman把百度AI注册、搜索、检测三个接口全部手动调通再写Spring Boot后端再写前端页面最后再接数据库和业务逻辑。这个顺序保证你每一步的依赖都处于最小可用状态排错范围也最小。不要一上来就追求把系统做完先把“一张人脸能从摄像头到数据库走通”这个主链路打通剩下的都是锦上添花。最后再分享一个小技巧开发调试阶段可以把百度接口每次返回的完整响应日志打出来包括请求参数和返回结果。对接第三方API时很多问题用肉眼看响应日志比看官方文档更快尤其是那些返回了错误码但文档描述模糊的场景实际响应里往往带着更具体的提示信息。等系统稳定了再把日志级别调整到INFO去掉敏感数据即可。本文还有配套的精品资源点击获取
返回列表