Logback日志脱敏实战:从原理到实现,构建安全防线
1. 项目概述为什么日志脱敏是开发者的必修课最近在排查一个线上问题时我翻看了几行应用日志瞬间惊出一身冷汗。日志里明晃晃地记录着用户的手机号、身份证号甚至还有一段未经处理的银行卡交易报文。这可不是危言耸听在数据安全法规日益严格的今天这样的日志一旦泄露轻则用户投诉、公司声誉受损重则面临严厉的监管处罚。这件事让我下定决心必须把日志脱敏这件事做扎实、做彻底。“logback实现日志信息脱敏”这个项目核心目标就是在日志输出的源头对敏感信息进行自动化、无侵入的掩码处理。它解决的远不止是合规问题更是对开发者责任心和技术素养的一次考验。想象一下无论是开发调试、还是线上运维你都能安心地把日志交给同事或第三方工具分析而无需担心数据泄露。这不仅仅是加几行配置而是构建一套可靠的数据安全防线。无论你是刚接触Logback的新手还是希望优化现有日志体系的老鸟掌握这套方法都能让你的应用在安全性和可维护性上提升一个档次。接下来我会把自己趟过的路、踩过的坑以及最终稳定运行的方案毫无保留地分享给你。2. 整体方案设计在日志体系的哪个环节“动手术”实现日志脱敏首先得想清楚在哪动手。Logback的日志处理流程就像一个流水线你的代码通过logger.info(“user: {}”, user)发出日志事件Event这个事件会经过过滤器Filter、格式化器Encoder/Layout最终被输出器Appender写到控制台、文件或网络。脱敏的核心思路就是在这个流水线上加装一个“净化处理器”。2.1 方案选型与权衡主流方案有三种各有优劣在编码器Encoder/Layout中处理这是最推荐、也是最优雅的方式。我们通常使用PatternLayoutEncoder来定义日志格式如%d{yyyy-MM-dd} [%thread] %-5level %logger{36} - %msg%n。我们可以自定义一个Layout在doLayout()方法中对即将输出的日志消息字符串进行脱敏替换。这个环节离最终输出最近能确保所有通过此Appender输出的日志都被处理且对业务代码零侵入。使用TurboFilter拦截TurboFilter在日志事件创建后、但被正式记录前起作用。它可以决定是否记录该事件也能修改事件中的消息Message。在这里做脱敏好处是能更早地干预甚至可以基于日志级别、Logger名做更精细的控制。但需要注意TurboFilter是全局的配置不当可能影响性能。在日志输出语句中手动处理也就是在代码里写logger.info(“phone: {}”, maskPhone(phone))。这是最不推荐的方式因为它严重侵入业务代码散落在各处难以维护极易遗漏且开发体验极差。为什么我最终选择了自定义Layout方案因为它实现了关注点分离。业务开发者只需关心打印什么日志而“如何安全地打印”这个非功能性需求由日志配置这个“基础设施”来统一保障。运维人员调整脱敏规则也无需改动代码只需更新配置文件。这种架构上的清晰是长期项目可维护性的基石。2.2 核心设计思路我们的目标是设计一个灵活、高效、低耦合的脱敏组件。其核心工作流程如下识别如何快速、准确地从一段日志文本中定位到敏感信息我们将采用“关键词正则表达式”双保险模式。替换识别后用什么规则进行掩码例如手机号保留前3后4身份证号保留前6后4银行卡号保留前6后4等。装配如何将这个组件无缝嵌入到现有的Logback配置中并支持灵活的规则配置这个设计必须兼顾性能因为日志输出可能是高频操作。我们不能为了安全而让应用性能骤降。因此在实现时会特别注意正则表达式的预编译、匹配策略的优化。3. 核心组件实现打造可配置的脱敏引擎理论说完了我们开始动手。我将一步步带你实现一个名为SensitiveDataMaskingLayout的自定义Layout。3.1 基础框架搭建首先创建一个继承自ch.qos.logback.classic.PatternLayout的类。继承它是因为我们通常已经使用了PatternLayout的格式现在只需要增强它的消息处理能力。package com.yourcompany.logback.mask; import ch.qos.logback.classic.PatternLayout; import ch.qos.logback.classic.spi.ILoggingEvent; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; public class SensitiveDataMaskingLayout extends PatternLayout { // 用于存储多条脱敏规则 private ListMaskingRule maskingRules new ArrayList(); Override public String doLayout(ILoggingEvent event) { // 1. 先让父类按照pattern格式化日志 String formattedMessage super.doLayout(event); // 2. 对格式化后的字符串应用所有脱敏规则 if (maskingRules ! null !maskingRules.isEmpty()) { for (MaskingRule rule : maskingRules) { formattedMessage rule.apply(formattedMessage); } } // 3. 返回脱敏后的最终字符串 return formattedMessage; } // 提供给logback配置文件注入规则的setter方法 public void addMaskingRule(MaskingRule rule) { this.maskingRules.add(rule); } }3.2 定义脱敏规则实体接下来定义一个MaskingRule类它封装了一条完整的脱敏规则匹配模式正则和替换逻辑。package com.yourcompany.logback.mask; import java.util.regex.Matcher; import java.util.regex.Pattern; public class MaskingRule { // 规则描述方便识别 private String name; // 预编译的正则表达式提升性能 private Pattern regexPattern; // 替换模板使用$1, $2等引用分组 private String replacement; public MaskingRule(String name, String regex, String replacement) { this.name name; this.regexPattern Pattern.compile(regex, Pattern.CASE_INSENSITIVE); this.replacement replacement; } public String apply(String input) { if (input null || input.isEmpty()) { return input; } try { Matcher matcher regexPattern.matcher(input); // 替换所有匹配项 return matcher.replaceAll(replacement); } catch (Exception e) { // 脱敏规则执行出错不能影响主流程记录警告并返回原内容 // 这里可以打印到System.err但注意不要递归触发日志 System.err.println([MaskingRule Error] Rule \ name \ failed: e.getMessage()); return input; } } // Getter and Setter 省略logback通过反射设置属性需要它们 public String getName() { return name; } public void setName(String name) { this.name name; } public String getRegex() { return regexPattern.pattern(); } public void setRegex(String regex) { this.regexPattern Pattern.compile(regex, Pattern.CASE_INSENSITIVE); } public String getReplacement() { return replacement; } public void setReplacement(String replacement) { this.replacement replacement; } }关键点解析预编译PatternPattern.compile在规则初始化时执行一次避免了在每次日志输出时重复编译正则这是性能优化的关键。异常处理脱敏是辅助功能绝不能因为一条规则写错导致日志输出崩溃。因此apply方法内做了try-catch出错时打印错误信息并返回原字符串。大小写不敏感Pattern.CASE_INSENSITIVE使得规则能匹配“idCard”、“IDcard”等多种写法更健壮。3.3 配置Logback以使用自定义Layout现在我们需要在logback-spring.xml或logback.xml中配置我们的脱敏组件。?xml version1.0 encodingUTF-8? configuration !-- 定义脱敏规则Bean -- rule nameMASK_ID_CARD classcom.yourcompany.logback.mask.MaskingRule name身份证号脱敏/name !-- 匹配15位或18位身份证号考虑前后可能有其他字符或引号 -- regex(\b\d{6})(\d{8,11})(\d{3}[0-9Xx]\b)/regex !-- $1代表第一个分组前6位$3代表第三个分组最后4位或3位校验位中间部分替换为* -- replacement$1********$3/replacement /rule rule nameMASK_PHONE classcom.yourcompany.logback.mask.MaskingRule name手机号脱敏/name !-- 匹配11位手机号考虑常见分隔符如-、空格 -- regex(\b1[3-9]\d{1,2})[-\s]?(\d{4})[-\s]?(\d{4}\b)/regex !-- 保留前3位和后4位 -- replacement$1****$3/replacement /rule rule nameMASK_BANK_CARD classcom.yourcompany.logback.mask.MaskingRule name银行卡号脱敏/name !-- 匹配16-19位银行卡号 -- regex(\b\d{6})(\d{6,11})(\d{4}\b)/regex replacement$1******$3/replacement /rule !-- 自定义脱敏Layout -- layout classcom.yourcompany.logback.mask.SensitiveDataMaskingLayout !-- 继承常用的日志模式 -- pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n/pattern !-- 注入上面定义的脱敏规则 -- rule-ref refMASK_ID_CARD/ rule-ref refMASK_PHONE/ rule-ref refMASK_BANK_CARD/ /layout !-- 将脱敏Layout应用到ConsoleAppender -- appender nameCONSOLE classch.qos.logback.core.ConsoleAppender encoder !-- 关键这里使用我们自定义的layout -- layout classcom.yourcompany.logback.mask.SensitiveDataMaskingLayout pattern%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/pattern rule-ref refMASK_ID_CARD/ rule-ref refMASK_PHONE/ /layout /encoder /appender !-- 也可以应用到FileAppender实现文件日志的自动脱敏 -- appender nameFILE classch.qos.logback.core.rolling.RollingFileAppender file./logs/app.log/file rollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicy fileNamePattern./logs/app.%d{yyyy-MM-dd}.log/fileNamePattern maxHistory30/maxHistory /rollingPolicy encoder layout classcom.yourcompany.logback.mask.SensitiveDataMaskingLayout pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n/pattern !-- 文件日志可以配置更全的规则 -- rule-ref refMASK_ID_CARD/ rule-ref refMASK_PHONE/ rule-ref refMASK_BANK_CARD/ /layout /encoder /appender root levelINFO appender-ref refCONSOLE/ appender-ref refFILE/ /root /configuration注意上面的rule和rule-ref标签是Logback的扩展语法需要配合自定义解析器。更通用的做法是直接在layout标签内通过maskingRule子元素配置但这需要更复杂的插件开发。为了快速上手一个更简单的替代方案是不在XML中定义MaskingRuleBean而是在SensitiveDataMaskingLayout类中通过init()方法静态初始化规则列表。我们先按通用思路理解架构后续会给出简化实现。4. 简化实战快速集成与配置技巧考虑到自定义标签的复杂性我们采用一个更务实的简化方案将规则定义在Java代码中通过系统属性或环境变量控制。4.1 改进的SensitiveDataMaskingLayout简化配置版public class SensitiveDataMaskingLayout extends PatternLayout { private ListMaskingRule maskingRules new ArrayList(); public SensitiveDataMaskingLayout() { // 在构造函数或init方法中初始化默认规则 initDefaultRules(); } private void initDefaultRules() { // 1. 身份证号 (15位或18位) maskingRules.add(new MaskingRule(ID_CARD, (\\b\\d{6})(\\d{8,11})(\\d{3}[0-9Xx]\\b), $1********$3)); // 2. 手机号 (11位) maskingRules.add(new MaskingRule(PHONE, (\\b1[3-9]\\d{1,2})[-\\s]?(\\d{4})[-\\s]?(\\d{4}\\b), $1****$3)); // 3. 邮箱 (用户名部分脱敏) maskingRules.add(new MaskingRule(EMAIL, (\\b)[\\w.-]([\\w-]\\.)[\\w-]{2,4}(\\b), $1***$2)); // 4. 银行卡 (16-19位) maskingRules.add(new MaskingRule(BANK_CARD, (\\b\\d{6})(\\d{6,11})(\\d{4}\\b), $1******$3)); } // 可以提供一个方法允许通过配置文件添加额外规则需解析字符串 public void addRuleFromString(String ruleStr) { // 格式name,regex,replacement (例如“地址,(\b地址[:]\s*)([^,\s]),$1***”) String[] parts ruleStr.split(,, 3); if (parts.length 3) { maskingRules.add(new MaskingRule(parts[0], parts[1], parts[2])); } } Override public String doLayout(ILoggingEvent event) { String message super.doLayout(event); for (MaskingRule rule : maskingRules) { message rule.apply(message); } return message; } }4.2 对应的Logback XML配置简化版现在XML配置变得非常简洁只需要声明使用我们的Layout即可。configuration appender nameCONSOLE classch.qos.logback.core.ConsoleAppender encoder layout classcom.yourcompany.logback.mask.SensitiveDataMaskingLayout !-- 可以在这里添加自定义pattern规则已在Java代码中初始化 -- pattern%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/pattern /layout /encoder /appender root levelINFO appender-ref refCONSOLE / /root /configuration如何动态添加规则你可以通过JVM启动参数传递规则然后在Layout的初始化代码中读取。例如String extraRules System.getProperty(logback.masking.rules); if (extraRules ! null) { for (String ruleLine : extraRules.split(;)) { addRuleFromString(ruleLine); } }启动命令java -Dlogback.masking.rules自定义规则1,regex1,rep1;自定义规则2,regex2,rep2 -jar yourapp.jar4.3 测试与验证写一段简单的测试代码看看效果import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LogTest { private static final Logger logger LoggerFactory.getLogger(LogTest.class); public static void main(String[] args) { String idCard 110101199003077856; String phone 13800138000; String email zhangsanexample.com; String bankCard 6228480012345678901; logger.info(用户注册身份证{} 手机{} 邮箱{}, idCard, phone, email); logger.info(发起支付卡号{}, bankCard); logger.debug(调试信息原始卡号{}, bankCard); // DEBUG级别可能不会输出取决于配置 } }预期输出控制台14:25:30.123 [main] INFO com.example.LogTest - 用户注册身份证110101********7856 手机138****8000 邮箱***example.com 14:25:30.124 [main] INFO com.example.LogTest - 发起支付卡号622848******8901可以看到敏感信息已经被成功替换为星号而日志的格式、级别等其他信息完全保持不变。5. 高级话题与性能优化基础功能实现后我们需要考虑更多生产环境会遇到的问题。5.1 处理JSON格式的日志现在很多应用使用JSON格式日志便于接入ELK等日志分析系统。脱敏需要处理结构化消息。假设我们使用net.logstash.logback.encoder.LogstashEncoder。思路JSON编码器通常会将日志事件转换为一个JSON对象。我们有两种方案自定义LoggingEvent实现一个包装类在getFormattedMessage()方法返回脱敏后的消息。但这比较复杂。后置处理器更推荐使用Logback的compositeEncoder或者寻找支持MessageFormatter的编码器在消息被序列化为JSON字符串前进行脱敏。一个实践方案是使用LoggingEventCompositeJsonEncoder并搭配自定义的JsonProvider。这里提供一个概念性更强的简化思路继承LogstashEncoder重写其格式化消息的方法。public class MaskingLogstashEncoder extends LogstashEncoder { private ListMaskingRule maskingRules new ArrayList(); public MaskingLogstashEncoder() { initDefaultRules(); } Override public String doLayout(ILoggingEvent event) { // 先获取原始消息 String originalMessage event.getFormattedMessage(); // 应用脱敏规则 String maskedMessage originalMessage; for (MaskingRule rule : maskingRules) { maskedMessage rule.apply(maskedMessage); } // 创建一个事件的副本替换消息内容注意ILoggingEvent不可变需要自定义实现 // 此处简化描述实际需使用自定义的LoggingEventWrapper ILoggingEvent maskedEvent new MaskedLoggingEventWrapper(event, maskedMessage); // 调用父类方法序列化包装后的事件 return super.doLayout(maskedEvent); } // ... 省略MaskedLoggingEventWrapper的实现细节 }然后在XML中配置appender nameJSON_FILE classch.qos.logback.core.rolling.RollingFileAppender encoder classcom.yourcompany.logback.mask.MaskingLogstashEncoder/ /appender5.2 性能考量与优化正则表达式是性能关键点。不当使用会导致CPU飙升。预编译我们已经做了确保Pattern只编译一次。正则复杂度避免使用贪婪匹配.*和回溯过多的复杂正则。我们的规则都尽量精确锚定\b表示单词边界。匹配顺序将最常出现、最容易匹配的规则放在前面。例如手机号通常比身份证号出现更频繁。短路优化如果某条日志经判断完全不包含敏感信息关键词如“phone”、“id”可以跳过所有正则匹配。可以在doLayout中先做一个简单的contains关键词检查。异步日志务必使用AsyncAppender。将耗时的脱敏计算尽管已优化放入单独的线程池避免阻塞业务线程。appender nameASYNC_FILE classch.qos.logback.classic.AsyncAppender queueSize512/queueSize discardingThreshold0/discardingThreshold appender-ref refFILE / /appender5.3 规则管理与动态更新生产环境的脱敏规则可能需要动态调整如新增一种证件类型。方案一外部化配置将规则定义在独立的配置文件如masking-rules.yaml中由Layout定时如每分钟检查并重新加载。方案二中心化配置结合配置中心Apollo, Nacos监听配置变化动态更新内存中的规则列表。此时需注意线程安全更新规则时可能需要加锁或使用CopyOnWriteArrayList。热更新注意事项更新正则表达式时旧的预编译Pattern对象需要被丢弃新的规则生效。要确保在更新过程中正在处理的日志不会因为规则不一致而导致部分脱敏失败。6. 常见问题排查与实战心得在实际部署和运维中你肯定会遇到一些意想不到的情况。下面是我总结的“避坑指南”。6.1 问题排查速查表问题现象可能原因排查步骤与解决方案日志中敏感信息完全没脱敏1. 自定义Layout类未正确加载。2. Appender配置错误未使用自定义Encoder/Layout。3. 规则正则表达式不匹配实际日志格式。1. 检查jar包依赖确保类在classpath中。2. 在Layout构造函数或start()方法中加入System.out.println调试确认是否被初始化。3. 检查XML配置确认layout或encoder的class属性指向正确。4. 打印一条标准格式的测试日志用在线正则工具如regex101.com验证你的正则是否能匹配。部分信息被错误脱敏误杀正则表达式过于宽泛匹配了非敏感信息。1. 收紧正则边界使用\b单词边界或更具体的上下文。2. 例如将匹配手机号的正则从\d{11}改为(1[3-9]\d{9})并考虑前后是否有phone等标识。3.重要在预发环境进行充分的回归测试覆盖各种边缘case的日志。日志输出性能明显下降1. 正则表达式过于复杂或低效。2. 同步日志输出且脱敏计算耗时。3. 规则数量过多。1. 使用AsyncAppender异步输出日志。2. 优化正则避免回溯。使用(?:)非捕获分组提升少许性能。3. 考虑实现“关键词过滤器”如果日志中不包含“id”、“phone”等关键词则跳过所有正则匹配。JSON日志脱敏后格式错误脱敏处理破坏了JSON结构如转义字符处理不当。1. 确保脱敏操作在消息被序列化为JSON字符串之前进行而不是之后。这就是为什么推荐用自定义Encoder或包装ILoggingEvent。2. 如果是对最终JSON字符串脱敏要小心处理字符串中的转义引号\。动态更新规则后不生效规则列表未线程安全或更新逻辑有bug。1. 将ListMaskingRule替换为CopyOnWriteArrayList。2. 检查配置中心监听器确保能正确触发并重新初始化规则列表。6.2 实操心得与建议白名单与黑名单思维不要只依赖黑名单正则匹配脱敏。对于核心业务对象如User、Order可以考虑在toString()方法中直接返回脱敏后的字符串。这是最彻底的源头控制。日志级别区分在DEBUG或TRACE级别有时为了排查极端问题可能需要看到完整信息。可以设计两套规则一套给INFO/WARN/ERROR级别用严格脱敏另一套给DEBUG/TRACE用部分脱敏或不脱敏。可以通过在Layout中判断event.getLevel()来实现。单元测试必不可少为你的MaskingRule和SensitiveDataMaskingLayout编写全面的单元测试覆盖各种边界情况空值、超长字符串、混合多类敏感信息、特殊字符、Unicode字符等。监控与审计可以考虑在脱敏组件中增加一个轻量的审计日志输出到独立的、权限更高的文件记录下哪些日志在什么时间被脱敏了只记录元数据如规则名、时间、Logger名绝不记录原始数据便于事后审计和规则优化。不要忽视异常堆栈异常堆栈信息里也可能包含敏感数据例如SQLException可能包含SQL语句和参数。我们的PatternLayout默认会处理throwableProxy但自定义Layout需要确保重写的方法也正确处理了异常信息可以递归地对堆栈字符串应用脱敏规则。最后我想强调的是日志脱敏不是一个“配置上就完事”的功能而是一个需要持续运营和优化的过程。随着业务发展新的敏感字段会出现旧的规则可能需要调整。建立一种机制让开发和运维同学能方便地报告漏脱敏的日志并快速更新规则同样重要。这套方案为你打下了坚实的基础但真正的安全来自于对细节的持续关注和对流程的不断完善。

相关新闻

CI/CD 流水线实战(9):流水线通知与可观测

CI/CD 流水线实战(9):流水线通知与可观测

上一篇已经建立第 8 层交付能力。本篇聚焦“可行动的交付信号”:不是展示一个绿色图标,而是建立可解释、可复现、失败后能安全停止的工程契约。读完后,读者应能把示例中的阶段、证据和门槛迁移到自己的语言与平台,并知道每个选择为…

2026/8/26 20:37:59 阅读更多 →
吸尘器怎么选?从280AW大吸力到折叠显尘,石头H50体验解析

吸尘器怎么选?从280AW大吸力到折叠显尘,石头H50体验解析

开头先讲一个我自己的观察:给家里选吸尘器的时候,大多数人都会盯着“吸力”这个数字看。吸力大不大、能不能把瓜子壳吸起来、能不能把床底灰尘一次带出来,好像只要吸力足够,其他问题都会自动消失。但实际用过几台不同定位的机器之…

2026/8/26 20:37:59 阅读更多 →
鸿蒙开发工程师核心技能与面试全攻略

鸿蒙开发工程师核心技能与面试全攻略

1. 鸿蒙开发工程师的职业定位与技术图谱 鸿蒙操作系统作为新一代智能终端操作系统,其开发者需要具备与传统移动开发差异化的技术栈。从我的实际招聘经验来看,优秀的鸿蒙工程师往往呈现"T型能力结构":既要对HarmonyOS核心机制有纵深…

2026/8/26 20:37:59 阅读更多 →

最新新闻

通用物体实例分割数据集zip处理指南:从解压到YOLOv8训练全攻略

通用物体实例分割数据集zip处理指南:从解压到YOLOv8训练全攻略

简介:在计算机视觉工程实践中,拿到一份带标注的数据集压缩包,如何从零开始完成数据验收、格式转换与模型训练,是很多开发者面临的现实问题。实例分割作为比目标检测更精细的像素级识别任务,对标注格式、数据质量与训练…

2026/8/26 21:54:58 阅读更多 →
Android NDK 交叉编译 proot:从源码迁移到原生可执行文件

Android NDK 交叉编译 proot:从源码迁移到原生可执行文件

1. 项目概述:为什么要把 proot 搬到 Android 上? 如果你是一个喜欢在 Android 设备上折腾 Linux 环境的开发者或爱好者,那么 proot 这个名字你一定不陌生。它是一个用户空间的 chroot 和 mount --bind 命令的替代品,简单来…

2026/8/26 21:54:58 阅读更多 →
数字电路入门:从逻辑门到三人表决器与交通灯控制器设计

数字电路入门:从逻辑门到三人表决器与交通灯控制器设计

1. 从“模拟”到“数字”:为什么我们需要逻辑电路?如果你玩过老式的收音机,拧动调台旋钮时,指针会平滑地划过刻度盘,喇叭里的声音从模糊到清晰,这个过程是连续的。这就是模拟信号的世界——电压、电流、声音…

2026/8/26 21:54:58 阅读更多 →
MathorCup B题实战:甲骨文图像分割与识别技术全解析

MathorCup B题实战:甲骨文图像分割与识别技术全解析

1. 项目概述:从“妈妈杯”到甲骨文图像识别的实战跨越 每年三四月份,数学建模圈子里最热闹的话题之一,肯定少不了MathorCup,大家更习惯叫它“妈妈杯”。作为国内规模大、认可度高的数学应用挑战赛,它每年的赛题都紧贴前…

2026/8/26 21:54:58 阅读更多 →
Bot自主操作信任设计:构建可控、可审计、可回滚的工程机制

Bot自主操作信任设计:构建可控、可审计、可回滚的工程机制

当一个 Bot 只会聊天时,我们对它的要求很简单,回答准确、语气自然就够了。可一旦 Bot 开始“动手操作”——自动拉群、自动调接口、自动改配置、自动提单,问题就完全变了。最近微信 bot、grok bot 这类带有自主操作能力的助手关注度很高&…

2026/8/26 21:54:58 阅读更多 →
华为OD机试采样过滤算法多语言实现与优化

华为OD机试采样过滤算法多语言实现与优化

1. 项目背景与核心需求 华为OD机试作为华为技术岗位的重要选拔环节,其双机位监考模式下的编程题往往需要考生在算法设计、代码规范、边界处理等方面展现出扎实的功底。"采样过滤"作为C卷的典型题型,主要考察以下核心能力: 多语言实…

2026/8/26 21:53:58 阅读更多 →

日新闻

Python random 模块常用函数详解:从入门到实战

Python random 模块常用函数详解:从入门到实战

目录 1. 引言2. 准备工作3. 基础随机函数4. 序列相关函数5. 随机种子与复现6. 实战案例7. 注意事项8. 常见问题与排查9. 总结 1. 引言 摘要: 本文系统介绍 Python 标准库 random 模块中最常用的随机数生成函数。内容涵盖基础随机函数(random()、unifor…

2026/8/26 0:00:40 阅读更多 →
《Microsoft Sql server 2008 Internals》读书笔记--第三章Databases and Database Files(2)

《Microsoft Sql server 2008 Internals》读书笔记--第三章Databases and Database Files(2)

《Microsoft Sql server 2008 Internals》索引目录: 《Microsoft Sql server 2008 Internals》读书笔记--目录索引 在上篇文章中,主要介绍了创建数据库的基本语法和FileGroup的初步知识。需要注意的是: 关于FileGroup 如果你的系统是用Raid设备直接存…

2026/8/26 1:18:18 阅读更多 →
政务AI智能体怎么建?三种模式、三步路径与四个误区

政务AI智能体怎么建?三种模式、三步路径与四个误区

政务AI智能体已经从概念试点阶段,转入了政务服务的常态化落地应用;在实际使用过程中,它能自主理解办事需求、辅助完成填报申报、开展材料预审,并联动多个系统协同作业,真正嵌入到政务办理的全流程当中。但在落地推进过…

2026/8/26 1:18:18 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/26 14:45:33 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/26 17:46:43 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/26 14:46:37 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/26 3:50:20 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/26 17:46:39 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/26 1:24:05 阅读更多 →