Activiti HistoryService实战:历史数据查询、清理与归档指南
1. 为什么流程明明跑完了还得单独维护一套历史数据学习Activiti的时候大多数人会把精力放在流程定义部署、RuntimeService启动流程、TaskService处理任务这些正在发生的事情上。我一开始也是这样直到某个项目上线大半年后业务方突然来找我要一份下季度预算审批流程的平均耗时我才意识到自己对HistoryService的理解远远不够。HistoryService存在的根本原因其实一句话就能说清运行时数据是临时的历史数据才是永久的。Activiti的运行时表ACT_RU_*系列里流程实例一旦到达结束状态引擎就会把相关记录清掉尤其是ACT_RU_EXECUTION、ACT_RU_TASK这些表几乎不留痕迹。如果当时没有把过程数据归档到历史表后面想复盘任何一个流程实例的完整轨迹都会面临无据可查的局面。所以这个服务解决的核心问题就是把流程实例从生到死的全过程落盘并提供一套统一查询入口。包括实例什么时候启动、什么时间结束、每个节点谁处理的、每个任务的受理人和办理时长、流程变量每次变更的痕迹、审批意见附件的关联信息。说白了它就是Activiti的监控录像和账本。这篇文章适合两类人一类是刚接触Activiti、正在逐个学习七大Service的初学者另一类是已经把流程跑起来、但发现历史数据越积越多、不知道该怎么查怎么清理的实战开发者。前者可以从这篇文章建立起对HistoryService的完整认知框架后者可以直接跳到第4节和第5节那些都是我在生产环境里实打实趟出来的经验。2. 先搞懂落盘结构ACT_HI_系列表的字段与关联关系2.1 五张核心历史表的职责划分HistoryService虽然是一个Java服务接口但底层对应的其实是数据库里那一组以ACT_HI_开头的历史表。我建议任何学习这个服务的人都先打开数据库客户端把这张表看一遍比光背API高效得多。历史表存储内容关键字段与运行时表的对应关系ACT_HI_PROCINST流程实例的历史信息启动/结束时间、业务Key、结束原因ID_, PROC_DEF_ID_, START_TIME_, END_TIME_, BUSINESS_KEY_对应ACT_RU_EXECUTION中type为root的实例ACT_HI_ACTINST流程中每个节点活动的执行历史ID_, PROC_INST_ID_, ACT_ID_, START_TIME_, END_TIME_对应ACT_RU_ACTINSTACT_HI_TASKINST用户任务的历史记录受理人、办理时间、办理时长ID_, PROC_INST_ID_, TASK_DEF_KEY_, ASSIGNEE_, CLAIM_TIME_对应ACT_RU_TASKACT_HI_VARINST流程变量的最终值快照ID_, PROC_INST_ID_, NAME_, VAR_TYPE_, TEXT_对应ACT_RU_VARIABLEACT_HI_DETAIL变量变更过程的明细记录每次修改都留痕ID_, PROC_INST_ID_, NAME_, TEXT_, TIME_运行时无对应是历史服务独有这几张表的写入时机不同理解这一点对排查问题特别重要。ACT_HI_PROCINST在流程实例启动那一刻就开始写ACT_HI_ACTINST在节点进入时插入一条节点结束时更新END_TIME_ACT_HI_TASKINST是在任务创建和完成时分别写入和更新ACT_HI_VARINST是变量第一次赋值时写入快照ACT_HI_DETAIL则是在每次变量变化时都追加一条这个表在某些项目里膨胀速度让人头疼后面第5节我会专门展开。2.2 通过关联字段把数据串起来看全貌这五张表不是孤立的核心关联字段是PROC_INST_ID_。我实际排查问题时经常一条SQL从实例一路查到最细粒度的变量变更SELECT pi.ID_ AS procInstId, pi.START_TIME_ AS procStart, pi.END_TIME_ AS procEnd, ai.ACT_ID_ AS activityId, ai.START_TIME_ AS actStart, ai.END_TIME_ AS actEnd, ti.ASSIGNEE_ AS assignee, v.NAME_ AS varName, v.TEXT_ AS varValue FROM ACT_HI_PROCINST pi LEFT JOIN ACT_HI_ACTINST ai ON ai.PROC_INST_ID_ pi.ID_ LEFT JOIN ACT_HI_TASKINST ti ON ti.PROC_INST_ID_ pi.ID_ LEFT JOIN ACT_HI_VARINST v ON v.PROC_INST_ID_ pi.ID_ WHERE pi.ID_ 某流程实例ID ORDER BY ai.START_TIME_;这里有一个很隐蔽的对应关系需要大家注意ACT_HI_ACTINST.ID_与ACT_HI_TASKINST.ACT_ID_并不是简单地一一对应。ACT_HI_TASKINST表里的ACT_ID_字段实际上存的是节点定义ID也就是BPMN里那个userTask idxxx的id而ACT_HI_ACTINST里ACT_ID_也是节点定义ID。两者如果想精确匹配通常需要用PROC_INST_ID_ ACT_ID_ START_TIME_一组字段来定位单纯用ID_直接join容易查出重复数据这是我在做节点耗时统计时踩过的坑。2.3 历史数据什么时候才愿意写history配置级别我刚接触的时候非常困惑一个问题为什么我明明执行了流程ACT_HI_DETAIL表却是空的后来才弄明白历史表的写入受引擎配置项history控制它有几个级别none不记录任何历史生产环境几乎没人这么配因为流程等于没有留痕activity记录流程实例和活动实例但不记录变量明细audit默认值记录实例、活动、任务、变量快照但不记录变量每次变更的明细full完整记录所有历史数据包括ACT_HI_DETAIL里变量每次赋值的变化默认是audit这意味着如果你不做特殊配置ACT_HI_DETAIL表永远是空的。判断自己引擎当前是什么级别可以这样查ProcessEngineConfiguration config processEngine.getProcessEngineConfiguration(); String historyLevel config.getHistory(); System.out.println(historyLevel); // 输出 audit / full / activity / none这里要提醒一句修改history配置级别后一定要清空已有的历史表数据再重启引擎否则会出现新旧数据语义不一致的情况。比如从audit改成full旧数据没有明细记录统计口径就对不上了。不要问我是怎么知道的吃过一次数据对不上的亏之后就老实了。3. HistoryService核心API清单与实践写法3.1 查询类API历史数据的主要价值在查HistoryService对外提供了一套和RuntimeService、TaskService风格高度一致的查询API熟悉其中一个另外几个基本可以举一反三。我把日常用到的核心查询按使用频率排个序查流程实例历史ListHistoricProcessInstance list historyService .createHistoricProcessInstanceQuery() .finished() // 只查已结束的实例 .processDefinitionKey(purchaseApproval) // 按流程定义Key过滤 .startedAfter(DateUtil.parse(2024-01-01)) // 开始时间范围 .orderByProcessInstanceEndTime() // 按结束时间排序 .desc() // 倒序 .list(); for (HistoricProcessInstance hpi : list) { String id hpi.getId(); String bizKey hpi.getBusinessKey(); Date start hpi.getStartTime(); Date end hpi.getEndTime(); Long duration hpi.getDurationInMillis(); // 引擎帮我们算好了执行时长 }这个方法我几乎是天天用。getDurationInMillis()返回从启动到结束的毫秒数做流程耗时统计的时候不用自己拿两个时间相减。查任务历史ListHistoricTaskInstance taskList historyService .createHistoricTaskInstanceQuery() .processInstanceId(2501) .taskAssignee(某用户工号) // 查这个人处理过的所有任务 .finished() .orderByHistoricTaskInstanceEndTime() .asc() .list();注意HistoricTaskInstance上有一个getDurationInMillis()这个值对分析单一环节效率特别有用。比如我发现某个审批环节平均耗时明显高于其他环节就能直接锁定瓶颈。查变量历史HistoricVariableInstance variable historyService .createHistoricVariableInstanceQuery() .processInstanceId(2501) .variableName(amount) .singleResult(); Object value variable.getValue();这里有个小坑singleResult()方法要求在过滤条件下结果必须唯一否则会抛异常。如果你不确定某个流程实例是否反复设置过同名变量用.list()更稳妥。3.2 原生查询复杂统计场景的破局手段当统计需求复杂到一定程度比如要按部门分组统计每个流程的平均审批时长标准查询API就有点束手束脚了。这时可以用原生SQL查询接口ListMapString, Object result historyService .createNativeHistoricProcessInstanceQuery() .sql(SELECT KEY_, COUNT(*) AS cnt, AVG(DURATION_) AS avgDuration FROM ACT_HI_PROCINST WHERE END_TIME_ IS NOT NULL GROUP BY KEY_) .list();原生SQL接口传回的是一行行的Map。这里说一个容易翻车的点ACT_HI_PROCINST.DURATION_字段单位是毫秒且它是引擎在流程结束时写入的。但如果你直接拿END_TIME_ - START_TIME_来计算跨天的情况下结果里可能混进数据库时区转换的误差所以我建议统计场景统一用DURATION_字段别自己算。3.3 删除与清理类APIHistoryService不是只能查也能删。常用的删除接口包括deleteHistoricProcessInstance(String processInstanceId)删除指定流程实例的全部历史记录deleteHistoricProcessInstances(ListString ids)批量删除deleteHistoricProcessInstanceByIds(...)另一种批量删除变体按实际版本区分deleteHistoricTaskInstance(String taskId)删除单条任务历史deleteHistoricProcessInstancesAsync(...)异步批量删除适合海量数据清理关于删除方法我需要专门展开说一下因为这里面的坑是最多的。首先是删除顺序问题。如果你直接调用deleteHistoricProcessInstance删除一个流程实例的历史引擎内部其实要清理ACT_HI_PROCINST、ACT_HI_ACTINST、ACT_HI_TASKINST、ACT_HI_VARINST、ACT_HI_DETAIL多个表的数据。如果恰好某些子表的记录有外键约束指向主表记录有些团队会手动加外键提升数据完整性直接删主表会报外键约束错误。我自己的经验是不要给历史表加外键约束这个阶段的性能优先级远高于完整性。如果已经加了删除前需要先删子表数据顺序是ACT_HI_DETAIL - ACT_HI_VARINST - ACT_HI_TASKINST - ACT_HI_ACTINST - ACT_HI_PROCINST。其次是在运行中的实例历史删不掉。引擎的设计逻辑是删除历史记录时如果实例仍处于运行状态会直接忽略或抛异常。所以清理历史数据前一定要先通过finished()过滤只对已结束的实例执行删除。再次是异步批量删除的参数。这个API设计得有些别扭第一个参数是流程实例ID列表第二个传入查询条件二十秒测试下来正确的写法是ListString ids historyService .createHistoricProcessInstanceQuery() .finished() .processDefinitionKey(oldProcess) .list() .stream() .map(HistoricProcessInstance::getId) .collect(Collectors.toList()); if (!ids.isEmpty()) { historyService.deleteHistoricProcessInstancesAsync( ids, historyService.createHistoricProcessInstanceQuery().processInstanceIds(new HashSet(ids)) ); }网上很多帖子只写了第一个参数第二个参数传null实测会报NPE。引擎需要从第二个查询对象里获取要删除的数据上下文。4. 别等半年后再来处理历史数据的清理与归档策略4.1 数据膨胀是这样发生的我们先算一笔账。假设一个中等规模的公司每天跑300个流程实例每个实例平均经过8个节点产生8条ACT_HI_ACTINST记录、6条任务历史记录、5条变量快照。那么一个月下来ACT_HI_ACTINST300 x 8 x 30 ≈ 72000条ACT_HI_TASKINST300 x 6 x 30 ≈ 54000条ACT_HI_VARINST300 x 5 x 30 ≈ 45000条ACT_HI_PROCINST300 x 30 9000条这还是在每天300个实例的中低负载假设下。那些每天上千实例、单实例几十个节点的业务系统数据量轻而易举到几百万级别。ACT_HI_DETAIL表更夸张一条流程变量每次修改都会追加一条记录一个实例跑下来可能有上百条明细。数据量上来之后最先感知到的问题是引擎启动变慢。因为Activiti在启动时要扫描历史相关表做版本校验和统计表数据量越大启动越慢。其次是数据库备份时间暴涨查询接口响应肉眼可见地变慢。4.2 在线清理定时任务异步批量删除我的线上环境做法是每天凌晨业务低峰期跑一个清理任务只保留最近90天的已完成流程历史Component public class HistoryCleanupTask { Autowired private HistoryService historyService; Scheduled(cron 0 30 2 * * ?) // 每天凌晨2:30执行 public void cleanupExpiredHistory() { Date deadline DateUtil.offsetDay(new Date(), -90); ListHistoricProcessInstance expiredInstances historyService .createHistoricProcessInstanceQuery() .finished() .finishedBefore(deadline) .listPage(0, 500); // 每次只取500条防止一次加载太多内存 if (!expiredInstances.isEmpty()) { ListString ids expiredInstances.stream() .map(HistoricProcessInstance::getId) .collect(Collectors.toList()); historyService.deleteHistoricProcessInstancesAsync( ids, historyService.createHistoricProcessInstanceQuery() .processInstanceIds(new HashSet(ids)) ); } } }有几个细节务必注意。批次大小控制在500~1000一次性拉几万条ID出来即使异步删除也不推荐容易给数据库带去过大的IO压力。时间条件用finishedBefore(deadline)它的语义是在deadline之前结束的千万不要用startedBefore否则会把一个90天前启动但上周刚结束的流程也删了业务方来找你要历史数据的时候你就被动了。4.3 归档策略历史表和主业务库解耦在线清理能解决大部分数据只增不减的问题但有些场景不能简单删合规要求保留3年、业务需要分析历史趋势、财务要做跨年审计。这个时候考虑的就是归档而不是删除。我的建议方案是冷热分离。在线库只保留半年数据半年以上的历史数据定期ETL到独立的历史库甚至是数据仓库。迁移完对原表执行删除这样主业务库性能不受影响历史库可以专门根据分析需求设计索引和存储结构。具体做法是每天定时把超过180天且已结束的流程实例从历史表SELECT出来以JSON或者多行Insert的方式写入归档库然后删除在线库中对应记录。这块逻辑不复杂但我会强烈建议加上幂等标记——归档表里记录一个SOURCE_ID_每次迁移前先检查是否已存在否则一旦定时任务被手动触发两次归档库里就会出现重复数据。4.4 索引设计查询变慢最大的元凶很多人遇到历史数据查询慢第一反应是加服务器配置实际上90%的情况下是索引问题。以ACT_HI_ACTINST这张表为例默认索引只有主键和流程实例ID。如果你有按节点定义ID查所有历史或者按办理人查历史的需求默认索引完全帮不上忙。我给历史表做索引的建议是ACT_HI_PROCINST建议建(START_TIME_)或(END_TIME_)索引所有按时间维度的查询都用得到ACT_HI_ACTINST建议建(PROC_INST_ID_, ACT_ID_)联合索引做节点耗时分析时避免全表扫描ACT_HI_TASKINST建议建(ASSIGNEE_, END_TIME_)联合索引查某人处理过的历史任务是高频场景ACT_HI_VARINST建议建(PROC_INST_ID_, NAME_)联合索引这里特别注意一下Activiti版本升级后高版本的ACT_HI_PROCINST会新增一些字段比如某些版本迭代了DELETE_REASON_、BUSINESS_KEY_。你按照旧版本设计的索引不一定适配新版本引擎写入的数据量级升级后记得重建相关索引。5. 我在真实环境里踩过的几个坑5.1 NativeQuery返回List的泛型陷阱Activiti原生查询API的list()方法返回结果看起来是ListHistoricProcessInstance但实际运行的时候如果SQL里包含多表关联查询比如我上面那个关联ACT_HI_ACTINST的SQL引擎底层直接丢回一个List里面有时候并不是目标对象。我在一个项目里写过这样的代码ListHistoricProcessInstance list historyService .createNativeHistoricProcessInstanceQuery() .sql(SELECT pi.*, ai.ACT_ID_ FROM ACT_HI_PROCINST pi LEFT JOIN ACT_HI_ACTINST ai ON ai.PROC_INST_ID_ pi.ID_ WHERE ...) .list(); String actId list.get(0).getStartActivityId(); // 直接从这里拿ACT_ID_看起来没毛病但运行到getStartActivityId时抛了ClassCastException。原因是原生SQL返回的结果会被映射成原生DB行数据多列情况下转不成目标实体。解决办法是SQL里只SELECT目标表需要的列比如关联表只用来做过滤条件.sql(SELECT pi.* FROM ACT_HI_PROCINST pi WHERE pi.ID_ IN (SELECT PROC_INST_ID_ FROM ACT_HI_ACTINST WHERE ACT_ID_ someNode))这样写能正常映射回HistoricProcessInstance。说白了一句经验NativeQuery里SELECT的字段必须和目标接口对象完全对应宁可关联条件放在子查询里也别让查询结果里多出来目标对象以外的列。5.2 明明流程结束了历史任务就是删不掉这个问题的排查链路很有代表性。当时的现象是调用deleteHistoricTaskInstance(taskId)删除某条任务历史控制台没有报错但刷新数据库ACT_HI_TASKINST记录还在。我先怀疑是事务没提交——结果排除了。又怀疑是传错了taskId——打了日志确认ID完全正确。最后查源码才发现deleteHistoricTaskInstance这个方法在引擎内部是有条件判断的它不会删除ACT_HI_ACTINST中对应的活动记录同时也就不会级联删除TASKINST而且当任务对应的流程实例还没结束运行时状态仍然存在引擎默认该任务历史仍然处于活跃状态就会直接忽略删除操作。最终解决方案是如果要删除单条历史任务先检查流程实例整体状态。如果只是流程实例已经走到下一节点但实例未结束历史任务删不掉是正常的不需要纠结。如果确实要强制清理得走deleteHistoricProcessInstance整实例删除没有只删一条历史任务的完美解法。5.3 full模式半年不到磁盘报警有个项目为了完整审计需求把history级别设置成了full。半年之后收到磁盘容量报警检查发现ACT_HI_DETAIL表占了整个历史库近60%的空间。原因前面说过每set一次流程变量full模式就向ACT_HI_DETAIL表插入一条记录。我们的业务方在审批过程中频繁通过REST接口更新同一个流程变量比如合同金额一个流程跑完可能写了上百次每条detail记录连TEXT_字段带时间戳占用空间非常可观。我的处理建议是审计需求未必真的需要full级别。绝大多数谁在什么时候改了什么值的诉求通过ACT_HI_VARINST的快照就够用了它保留了每个变量最新一次的值。只有当你需要还原每一次修改变量的完整历史轨迹时比如财务系统要求追溯每次金额变更的审批依据才值得付出full级别的存储代价。而且从audit切到full前务必估算一下变量写入频率这个数据量再决定。5.4 拿历史表和运行时表Join查询的惨痛教训曾经为了做当前待办任务历史处理记录混合展示写过一条SQL把ACT_RU_TASK和ACT_HI_TASKINST做了UNION甚至LEFT JOIN。开发环境数据量小跑得飞快测试环境数据量一到百万级直接超时。后来我想明白了一个道理运行时表和历史表的数据生命周期是对立的。ACT_RU_TASK里存的都是没走完的任务ACT_HI_TASKINST里是已经结束的任务。两个表同时存在的记录极少业务上根本不构成关联关系。正确做法是分开查待办任务走TaskService.createTaskQuery()历史记录走HistoryService.createHistoricTaskInstanceQuery()在应用内存里做一个合并。别偷懒用一句大SQL搞定所有事情这是在给自己挖坑。6. 关于HistoryService我最后的建议如果你正在设计一个基于Activiti的业务系统我希望你记住这几件事。第一历史数据是业务资产不是技术垃圾。它里面藏着流程瓶颈、组织效率、审批规则合理性这些业务方最关心的指标。不要把HistoryService简单理解成增删改查的另一个Service多看几眼历史表的数据你会对整套流程引擎的运行逻辑有完全不一样的理解。第二不要只测试默认配置。历史数据相关的配置项history级别、异步执行器、批量删除的Batch窗口在开发环境数据量小的时候全都表现正常生产环境数据量上来才会暴露配置瓶颈。我的做法是在搭建环境的时候就用脚本把100个并发流程实例的历史数据灌进去压一遍提前观察ACT_HI_系列表的写入性能不要等到上线后再反应。第三关于清理策略千万别想着一劳永逸。我现在的做法是每次业务迭代都同步review一次历史数据保留策略跟业务方确认这些数据还需要留多久在这个基础上定期执行归档和清理。流程引擎跑多久历史数据治理就要持续多久。

相关新闻

JavaSE初学者课堂作业

JavaSE初学者课堂作业

摘要:本文是计算机大一新生对 JavaSE 学习内容的课堂总结。文章首先介绍了数据类型与程序逻辑控制两大基础知识点,随后规划了后续学习路线,包括面向对象、集合框架、异常处理、IO 流四个核心模块,并逐一说明它们与 AI 应用开发岗位…

2026/10/14 18:48:03 阅读更多 →
AntDesignPro of Vue权限管理实战:路由与按钮级权限设计

AntDesignPro of Vue权限管理实战:路由与按钮级权限设计

1. 权限管理在后台系统里到底管什么后台管理系统做久了,你会发现一个规律:功能越堆越多,最先扛不住的往往不是性能,而是权限。谁能看到哪个菜单、谁只能看不能改、谁连按钮都不该看见,这些问题如果一开始没设计好&…

2026/10/14 18:48:03 阅读更多 →
ponytail:当代职场的情绪标点与轻量协作语言

ponytail:当代职场的情绪标点与轻量协作语言

1. 项目概述:从“ponytail”这个词开始,我们到底在聊什么?“ponytail”这个词最近频繁出现在社交平台的评论区、弹幕和短视频标题里,但它早已不是字典里那个“马尾辫”的简单释义。我做内容运营和用户行为分析十多年,见…

2026/10/14 18:48:03 阅读更多 →

最新新闻

小白速通嵌入式第三天——计算机硬件组成及主要部件功能

小白速通嵌入式第三天——计算机硬件组成及主要部件功能

小白速通嵌入式第三天——计算机硬件组成及主要部件功能 目录 计算机硬件组成总览(冯诺依曼结构)中央处理单元 CPU存储器总线输入/输出控制高频考点与易错点速记 1. 计算机硬件组成总览 1.1 冯诺依曼体系五大部件(背) 计算机硬…

2026/10/14 19:34:47 阅读更多 →
Cocos Creator JS-OC交互避坑指南:参数、线程与签名的三重校准

Cocos Creator JS-OC交互避坑指南:参数、线程与签名的三重校准

1. 为什么Cocos Creator里JS与OC交互不是“写个接口就完事”?在某跨平台游戏项目中,我接手了一个已上线半年的iOS版本,核心功能是玩家点击一个特殊道具后,调用原生相册选择图片并上传至服务器。当时代码里只有一行看似干净的调用&…

2026/10/14 19:34:47 阅读更多 →
航天器电子电气紧固件安装工艺与Q/W 1036B标准解析

航天器电子电气紧固件安装工艺与Q/W 1036B标准解析

1. 航天器紧固件安装工艺的特殊性航天器电子电气产品的紧固件安装工艺与普通工业领域有着本质区别。在太空环境中,微重力、极端温度变化(-150℃至150℃)、高真空和强辐射等严苛条件对紧固连接提出了近乎苛刻的要求。Q/W 1036B-2016标准正是针…

2026/10/14 19:34:47 阅读更多 →
考虑时序相关性的蒙特卡洛场景生成与削减实战解析

考虑时序相关性的蒙特卡洛场景生成与削减实战解析

先交代一个背景:前一阵子帮某高校研究团队做新能源出力场景库建设,他们手里有一批某风电场的数年逐小时出力数据,要做随机调度优化。起初大家用的都是常规套路——先拟合每个时刻的边缘分布,再独立蒙特卡洛采样生成一千条“日场景…

2026/10/14 19:34:47 阅读更多 →
SpringBoot智能CRM系统开发实践与架构设计

SpringBoot智能CRM系统开发实践与架构设计

1. 项目概述"SpringBoot客户关系智能管理系统"是一个基于SpringBoot框架开发的现代化客户关系管理解决方案。这类系统在当今数字化商业环境中扮演着至关重要的角色,特别是在销售自动化、客户服务优化和数据分析领域。我在实际企业级应用开发中发现&#x…

2026/10/14 19:34:47 阅读更多 →
基于Zafer-Liu/Data-Analysis-Agent的智能数据分析助手:构建自动化洞察与大模型交互实战指南

基于Zafer-Liu/Data-Analysis-Agent的智能数据分析助手:构建自动化洞察与大模型交互实战指南

基于Zafer-Liu/Data-Analysis-Agent的智能数据分析助手:构建自动化洞察与大模型交互实战指南 在数据驱动决策的今天,数据分析的门槛依然存在,特别是对于非技术背景的业务人员来说,编写SQL或Python脚本往往是一道难以逾越的鸿沟。G…

2026/10/14 19:33:47 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/14 7:53:34 阅读更多 →