临安建设规划局网站河南建设工程质量监督局网站
2026/4/16 18:31:18 网站建设 项目流程
临安建设规划局网站,河南建设工程质量监督局网站,动态电子商务网站建设报告,自适用网站的建设一、接口核心需求分析 你提供的这段代码是Activiti工作流中查询指定任务的办理时间轴接口#xff0c;核心业务需求如下#xff1a; 关联查询#xff1a;根据传入的任务ID#xff08;taskId#xff09;#xff0c;先获取对应的流程实例ID#xff08;processInstanceId核心业务需求如下关联查询根据传入的任务IDtaskId先获取对应的流程实例IDprocessInstanceId历史轨迹查询查询该流程实例下所有“用户任务userTask”的历史执行记录按任务开始时间升序排列数据格式化将历史任务记录转换为前端易展示的TaskInfo对象包含任务名称、办理人、开始/结束时间、审批意见等核心信息结果返回返回结构化的任务办理时间轴列表支撑前端展示流程审批轨迹。二、代码逐段解析核心逻辑设计思路1. 流程实例ID关联StringprocessInstanceIdtaskService.createTaskQuery().taskId(taskId).singleResult().getProcessInstanceId();设计思路通过TaskService的taskQuery按taskId查询具体任务获取该任务所属的流程实例ID这是“任务→流程实例→历史任务”关联的核心步骤因为历史任务需按流程实例维度查询。风险点singleResult()可能返回null如taskId不存在直接调用getProcessInstanceId()会抛出空指针异常。2. 历史用户任务查询ListHistoricActivityInstancehistoryhistoryService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId)// 按流程实例过滤.activityType(userTask)// 仅查询用户任务排除网关、开始/结束节点等.orderByHistoricActivityInstanceStartTime().asc()// 按开始时间升序时间轴顺序.list();设计思路借助HistoryService的HistoricActivityInstanceQuery查询流程实例的历史活动记录核心过滤条件activityType(userTask)只保留人工办理的任务过滤自动节点如网关、服务任务符合“办理时间轴”的业务场景排序规则按任务开始时间升序保证时间轴从流程发起→后续审批的顺序展示。3. 历史数据转换为前端DTOListTaskInfoinfosnewArrayList();SimpleDateFormatsdfnewSimpleDateFormat(yyyy-MM-dd HH:mm:ss);history.stream().forEach(h-{TaskInfoinfonewTaskInfo();info.setProcessInstanceId(h.getProcessInstanceId());info.setStartTime(sdf.format(h.getStartTime()));if(h.getEndTime()!null){info.setEndTime(sdf.format(h.getEndTime()));}info.setAssignee(h.getAssignee());// 任务办理人info.setTaskName(h.getActivityName());// 任务名称如“采购经理审批”// 查询任务审批意见ListCommentcommentstaskService.getTaskComments(h.getTaskId());if(comments.size()0){info.setComment(comments.get(0).getFullMessage());}infos.add(info);});设计思路数据适配将Activiti原生的HistoricActivityInstance对象转换为自定义TaskInfo前端DTO屏蔽框架底层字段只返回业务所需信息时间格式化将Date类型的开始/结束时间转换为“yyyy-MM-dd HH:mm:ss”字符串便于前端展示审批意见关联通过taskService.getTaskComments(h.getTaskId())查询任务的审批备注评论取第一条作为核心意见。三、核心问题与优化方案1. 空指针异常最高优先级优化原代码存在多处空指针风险需补充校验ApiOperation(任务办理时间轴)RequestMapping(value/history/{taskId},methodRequestMethod.GET)ResponseBodypublicListTaskInfohistory(PathVariableStringtaskId){// 1. 校验入参if(StringUtils.isBlank(taskId)){returnCollections.emptyList();// 或返回AjaxResult提示参数为空}// 2. 查询任务时校验nullTasktasktaskService.createTaskQuery().taskId(taskId).singleResult();if(tasknull){returnCollections.emptyList();// 无对应任务返回空列表}StringprocessInstanceIdtask.getProcessInstanceId();// 3. 查询历史任务ListHistoricActivityInstancehistoryhistoryService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityType(userTask).orderByHistoricActivityInstanceStartTime().asc().list();ListTaskInfoinfosnewArrayList();SimpleDateFormatsdfnewSimpleDateFormat(yyyy-MM-dd HH:mm:ss);// 4. 遍历历史任务时避免空指针for(HistoricActivityInstanceh:history){if(hnull){continue;}TaskInfoinfonewTaskInfo();info.setProcessInstanceId(h.getProcessInstanceId());// 时间格式化校验if(h.getStartTime()!null){info.setStartTime(sdf.format(h.getStartTime()));}if(h.getEndTime()!null){info.setEndTime(sdf.format(h.getEndTime()));}info.setAssignee(h.getAssignee());info.setTaskName(h.getActivityName());// 审批意见查询校验taskId非空if(StringUtils.isNotBlank(h.getTaskId())){ListCommentcommentstaskService.getTaskComments(h.getTaskId());if(comments!null!comments.isEmpty()){info.setComment(comments.get(0).getFullMessage());}}infos.add(info);}returninfos;}2. 性能优化问题遍历历史任务时每次调用taskService.getTaskComments(h.getTaskId())都会发起一次数据库查询若历史任务较多如10会产生N1查询问题优化方案批量查询所有任务的审批意见减少数据库交互// 1. 先收集所有历史任务IDListStringtaskIdshistory.stream().filter(h-StringUtils.isNotBlank(h.getTaskId())).map(HistoricActivityInstance::getTaskId).collect(Collectors.toList());// 2. 批量查询评论需自定义SQL/扩展APIActiviti原生无批量查询评论接口// 示例通过自定义Mapper批量查询MapString,CommenttaskCommentMapcommentMapper.getCommentByTaskIds(taskIds);// 3. 遍历历史任务时直接从Map取值for(HistoricActivityInstanceh:history){// ... 其他赋值逻辑CommentcommenttaskCommentMap.get(h.getTaskId());if(comment!null){info.setComment(comment.getFullMessage());}}3. 时间格式化优化问题SimpleDateFormat是非线程安全的若接口高并发调用可能出现时间格式化错误优化方案使用DateTimeFormatterJava 8替代DateTimeFormatterformatterDateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss);// 时间格式化if(h.getStartTime()!null){info.setStartTime(h.getStartTime().toInstant().atZone(ZoneId.systemDefault()).format(formatter));}if(h.getEndTime()!null){info.setEndTime(h.getEndTime().toInstant().atZone(ZoneId.systemDefault()).format(formatter));}4. 异常处理补充全局异常捕获避免接口抛出未处理的异常ApiOperation(任务办理时间轴)RequestMapping(value/history/{taskId},methodRequestMethod.GET)ResponseBodypublicAjaxResulthistory(PathVariableStringtaskId){// 改为返回统一响应体try{// 核心逻辑上述优化后的代码ListTaskInfoinfos...;returnAjaxResult.success(infos);}catch(Exceptione){log.error(查询任务办理时间轴失败taskId{},taskId,e);returnAjaxResult.error(查询任务办理轨迹失败e.getMessage());}}四、设计维度温习1. 架构设计分层设计接口属于“应用层”依赖Activiti的TaskService/HistoryService领域层完成数据查询符合分层架构规范DTO设计通过TaskInfo封装前端所需字段实现“领域模型→展示模型”的解耦避免直接返回框架原生对象。2. 扩展性设计多维度过滤可扩展支持按“办理人、任务状态、时间范围”过滤历史任务例如// 扩展仅查询指定办理人的任务historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityType(userTask).assignee(zhangsan)// 扩展过滤条件.list();多语言适配时间格式化可扩展支持国际化如DateTimeFormatter结合Locale审批意见扩展原代码仅取第一条评论可扩展返回所有评论或按评论类型过滤如“审批意见/备注”。3. 安全与规范权限控制建议添加权限校验如PreAuthorize仅允许流程参与人/管理员查询时间轴日志规范添加入参、出参日志便于问题排查log.info(查询任务办理时间轴taskId{},taskId);log.info(查询结果{},infos.size());五、核心总结维度核心要点需求核心按任务ID关联流程实例查询所有用户任务的历史轨迹格式化后返回办理时间、办理人、审批意见等信息设计亮点聚焦“用户任务”过滤非业务节点按时间升序保证时间轴顺序适配前端展示格式优化方向1. 补充空指针校验2. 替换线程不安全的SimpleDateFormat3. 批量查询评论避免N14. 统一异常处理和日志5. 添加权限控制扩展场景支持多条件过滤、多语言时间格式化、批量返回审批意见该接口是工作流审批轨迹展示的核心接口优化后可解决空指针、性能、线程安全等问题同时保持良好的扩展性适配企业级应用的生产环境需求。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询