门户网站开发流程,小程序开发需要哪些技术,合肥关键词快速排名,深圳罗湖企业网站建设疑问
状态from to合法性校验#xff0c;都是在代码中手动进行的吗#xff0c;不是状态机自动进行的#xff1f;
注解中from状态#xff0c;代表当前状态
和谁校验#xff1a;上下文中初始状态
怎么根据注解找到执行方法的
分析代码#xff0c;创建运单#xff0c;怎…疑问
状态from to合法性校验都是在代码中手动进行的吗不是状态机自动进行的
注解中from状态代表当前状态
和谁校验上下文中初始状态
怎么根据注解找到执行方法的
分析代码创建运单怎么关联到注解 Transit(from unsigned, to unsigned, on CREATE),的怎么根据注解找到执行方法的
package com.smcv.mall.tasks.statemachine;import com.alibaba.fastjson.JSON;
import com.smcv.mall.api.tasks.model.JghcTaskDTO.JghcTaskCreateForDP;
import com.smcv.mall.tasks.constant.ErrConstant;
import com.smcv.mall.tasks.ddd.domain.impl.TaskStatusTriggerService;
import com.smcv.mall.tasks.ddd.domain.inf.IDPStatusService;
import com.smcv.mall.tasks.exception.YlTaskException;
import com.smcv.mall.tasks.model.dto.DPTaskStatusChangeReqDTO;
import com.smcv.mall.tasks.statemachine.constant.DPEventEnum;
import com.smcv.mall.tasks.statemachine.constant.DPStateEnum;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.squirrelframework.foundation.fsm.annotation.StateMachineParameters;
import org.squirrelframework.foundation.fsm.annotation.Transit;
import org.squirrelframework.foundation.fsm.annotation.Transitions;
import org.squirrelframework.foundation.fsm.impl.AbstractUntypedStateMachine;/**
*/
Transitions({
//创建运单
Transit(from unsigned, to unsigned, on CREATE),/*** 未指派 - 执行中* 1.扫码抢单* 2.派单员指派* 3.自提单*/Transit(from unsigned, to executing, on ASSIGN_EXCUTING, callMethod assignExcuting),/*** 已指派 - 执行中* 1.扫码抢单* 2.派单员指派*/Transit(from signed, to executing, on ASSIGN_EXCUTING, callMethod assignExcuting),/*** 未指派 - 已指派* 1.超时指派* 2.司机抢单*/Transit(from unsigned, to signed, on ASSIGN_SIGNED),//执行运单Transit(from signed, to executing, on EXECUTING),//前往途经点Transit(from waitStart, to toStart, on CHILD_TOSTART, callMethod childTostart),//前往途经点 兼容老版本Transit(from contacted, to toStart, on CHILD_TOSTART, callMethod childTostart),//到达途经点Transit(from toStart, to toEnd, on CHILD_TOEND),//待出发 - 到达途经点Transit(from waitStart, to toEnd, on CHILD_WAITTOEND),//前往下一个途经点Transit(from toEnd, to toNextStart, on CHILD_TONEXTSTART, callMethod childTonextstart),//前往下一个途经点 兼容老版本Transit(from payed, to toNextStart, on CHILD_TONEXTSTART, callMethod childTonextstart),//运单完成Transit(from executing, to finished, on FINISH),//运单取消Transit(from unsigned, to canceled, on CANCEL, callMethod cancel),Transit(from signed, to canceled, on CANCEL, callMethod cancel),Transit(from executing, to canceled, on CANCEL, callMethod cancel),Transit(from canceled, to canceled, on CANCEL, callMethod cancel),//幂等性
})
StateMachineParameters(stateType DPStateEnum.class, eventType DPEventEnum.class, contextType DPContext.class)
Slf4j(topic task)
public class DPStateMachine extends AbstractUntypedStateMachine {private static final String LOG_PRE 【{}】地跑状态流转,orderNumber[{}],fromState[{}],toState[{}],event[{}],context[{}];protected ApplicationContext applicationContext;private IDPStatusService idpStatusService;/*** 初始化时候会调用类似后置处理器** param applicationContext*/
public void postConstruct(ApplicationContext applicationContext) {this.applicationContext applicationContext;
}/*** 开始执行之前的方法** param fromState* param event* param context*/
Override
protected void beforeTransitionBegin(Object fromState, Object event, Object context) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), ((DPContext) context).getOrderNumber(), fromState, null, event, context);//获取状态机服务类idpStatusService (IDPStatusService) ((DPContext) context).getIStatusService();
}/*** 事件触发之前被调用** param fromState* param toState* param event* param context*/
Override
protected void beforeActionInvoked(Object fromState, Object toState, Object event, Object context) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), ((DPContext) context).getOrderNumber(), fromState, toState, event, context);/*** 状态合理性校验*/DPContext dpContext (DPContext) context;if (!dpContext.isReentrantLock()) {//重入锁不需要状态合理性校验DPEventEnum dpEventEnum (DPEventEnum) event;((TaskStatusTriggerService) dpContext.getIStatusService()).checkFromState(fromState, toState, context, dpEventEnum);}
}/*** 非法状态流转** param fromState* param event* param context*/
Override
protected void afterTransitionDeclined(Object fromState, Object event, Object context) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), ((DPContext) context).getOrderNumber(), fromState, null, event, context);throw new YlTaskException(ErrConstant.BUSI_RETURN_ERR, 状态流转异常);
}/*** 正常执行完毕后执行的方法** param fromState* param toState* param event* param context*/
Override
protected void afterTransitionCompleted(Object fromState, Object toState, Object event, Object context) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), ((DPContext) context).getOrderNumber(), fromState, toState, event, context);
}/*** 执行异常** param fromState* param toState* param event* param context*/
SneakyThrows
Override
protected void afterTransitionCausedException(Object fromState, Object toState, Object event, Object context) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), ((DPContext) context).getOrderNumber(), fromState, toState, event, context);//此处不调用父类方法异常不会被抛出//super.afterTransitionCausedException(fromState, toState, event, context);if (getLastException().getTargetException() ! null) {//重写父类方法向外抛出自定义异常throw getLastException().getTargetException();} else {super.afterTransitionCausedException(fromState, toState, event, context);}
}/*** 状态机执行完毕必须执行的方法不管成功/失败与否** param fromState* param toState* param event* param context*/
Override
protected void afterTransitionEnd(Object fromState, Object toState, Object event, Object context) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), ((DPContext) context).getOrderNumber(), fromState, toState, event, context);super.afterTransitionEnd(fromState, toState, event, context);
}/*** 创建运单** param fromState* param toState* param dpEventEnum* param dpContext*/
public void transitFromunsignedTounsignedOnCREATE(DPStateEnum fromState, DPStateEnum toState, DPEventEnum dpEventEnum, DPContext dpContext) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), dpContext.getOrderNumber(), fromState, toState, dpEventEnum, dpContext);JghcTaskCreateForDP jghcTaskCreateForDP dpContext.getJghcTaskCreateForDP();jghcTaskCreateForDP.setServiceCode(dpContext.getCreateChannel());idpStatusService.createTask(jghcTaskCreateForDP);
}/*** 指派运单[状态流转到执行中]** param fromState* param toState* param dpEventEnum* param dpContext*/
public void assignExcuting(DPStateEnum fromState, DPStateEnum toState, DPEventEnum dpEventEnum, DPContext dpContext) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), dpContext.getOrderNumber(), fromState, toState, dpEventEnum, dpContext);DPTaskStatusChangeReqDTO dpTaskStatusChangeReqDTO dpContext.getDpTaskStatusChangeReqDTO();dpTaskStatusChangeReqDTO.setFromState(fromState);dpTaskStatusChangeReqDTO.setToState(toState);idpStatusService.assignExcuting(dpTaskStatusChangeReqDTO);
}/*** 指派运单[状态流转到已指派]** param fromState* param toState* param dpEventEnum* param dpContext*/
public void transitFromunsignedTosignedOnASSIGN_SIGNED(DPStateEnum fromState, DPStateEnum toState, DPEventEnum dpEventEnum, DPContext dpContext) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), dpContext.getOrderNumber(), fromState, toState, dpEventEnum, dpContext);DPTaskStatusChangeReqDTO dpTaskStatusChangeReqDTO dpContext.getDpTaskStatusChangeReqDTO();dpTaskStatusChangeReqDTO.setFromState(fromState);dpTaskStatusChangeReqDTO.setToState(toState);idpStatusService.assignSigned(dpTaskStatusChangeReqDTO);
}/*** 执行运单** param fromState* param toState* param dpEventEnum* param dpContext*/
public void transitFromsignedToexecutingOnEXECUTING(DPStateEnum fromState, DPStateEnum toState, DPEventEnum dpEventEnum, DPContext dpContext) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), dpContext.getOrderNumber(), fromState, toState, dpEventEnum, dpContext);DPTaskStatusChangeReqDTO dpTaskStatusChangeReqDTO dpContext.getDpTaskStatusChangeReqDTO();dpTaskStatusChangeReqDTO.setFromState(fromState);dpTaskStatusChangeReqDTO.setToState(toState);
// dpContext.setDpTaskStatusChan
在给定的代码中状态机的行为是通过 Transit 注解定义的这些注解指明了状态转移的规则和事件并且关联了执行的方法。具体来说Transit 注解配置了状态从 from 到 to 的转移条件以及触发该状态转移的事件 (on)。有些 Transit 注解还指定了 callMethod 属性表示当该转移发生时应该调用哪个方法来执行相关逻辑。
注解分析 java
Transit(from unsigned, to unsigned, on CREATE)
这个注解表示当事件 CREATE 发生时状态从 unsigned 转移到 unsigned。这是一种状态机的事件与状态的定义。
方法执行关联 方法名与注解中的 callMethod 对应 在注解中可以通过 callMethod 属性指定状态转换时需要调用的方法。如果 callMethod 被指定状态机在状态转换时会执行这个方法。例如 java Transit(from unsigned, to executing, on ASSIGN_EXCUTING, callMethod assignExcuting) 这个注解表示当事件 ASSIGN_EXCUTING 发生时状态从 unsigned 转移到 executing并且会调用 assignExcuting 方法。 方法调用的方式 对于状态机中的状态转换当事件触发时注解框架在这个例子中是 Squirrel 状态机库会通过反射查找并调用注解中指定的 callMethod 方法。具体来说框架会使用事件、状态和上下文信息来找到正确的方法并执行。 如何根据注解找到执行方法 在代码执行的过程中当事件发生并触发状态机的状态转换时状态机框架会检查该状态转换是否带有 callMethod。如果 callMethod 指定了方法名框架会使用反射机制去查找与该方法名匹配的实例方法并调用它。例如当 on CREATE 事件发生时如果没有指定 callMethod那么该状态转移会自动被处理状态变化本身不需要调用方法。但如果 callMethod 被指定状态转移发生时就会调用指定的方法如 transitFromunsignedTounsignedOnCREATE 方法。 如何定义方法 每个方法签名都应该与状态机的定义保持一致即方法应该接受 fromState、toState、event、context 等参数。例如在 transitFromunsignedTounsignedOnCREATE 方法中签名是 java public void transitFromunsignedTounsignedOnCREATE(DPStateEnum fromState, DPStateEnum toState, DPEventEnum dpEventEnum, DPContext dpContext) 这个方法的作用是处理从 unsigned 到 unsigned 状态的转换并且根据 CREATE 事件的触发执行特定的操作。其实现逻辑可以是创建运单等操作。
事件触发与方法调用的流程
触发事件当事件如 CREATE被触发时状态机会根据状态机的配置来查找与该事件相关的状态转移。查找对应的 Transit 注解框架会检查所有的 Transit 注解找出符合当前事件的注解。例如如果当前事件是 CREATE它会检查所有定义了 on CREATE 的注解。调用指定的方法如果某个 Transit 注解指定了 callMethod 属性如 transitFromunsignedTounsignedOnCREATE框架会使用反射来调用相应的方法。
例如下面这个注解 java
Transit(from unsigned, to unsigned, on CREATE)
当 CREATE 事件发生时框架会寻找与该事件相关的状态转移逻辑。如果没有指定 callMethod则仅处理状态转移。如果有指定方法如 transitFromunsignedTounsignedOnCREATE它会调用该方法来处理相关逻辑。
总结
注解中的 Transit 定义了事件与状态的转移规则。callMethod 属性允许开发者为状态转移指定自定义的处理方法。状态机框架使用反射来根据注解动态调用对应的方法。callMethod 指定的方法需要具备一定的签名通常包括 fromState、toState、event 和 context。
通过这种方式状态机可以动态地根据事件和状态转移配置执行预定的操作。 如果直接根据事件oncallMethod 找到对应的方法状态from to有什么用
你提到的问题是关于 状态机 中 Transit 注解中的 from 和 to 参数如果在事件处理时已经通过 on 和 callMethod 找到对应的方法那么 from 和 to 的作用是什么这两个参数的意义其实是非常重要的下面我会逐一解释它们在状态机中的作用。
1. 状态 (from 和 to) 用于验证状态转换
尽管 callMethod 指定了方法来执行特定的逻辑但是 from 和 to 这两个参数仍然有它们的关键作用尤其是在 验证和控制状态流转的合法性 方面。
主要作用
状态的合法性检查from 和 to 定义了状态机中状态的合法转换路径。它们确保了事件不会导致非法的状态跳跃保证了状态流转的一致性。保障状态流转的一致性通过定义明确的状态流转路径从 from 到 to状态机可以防止不符合逻辑的状态转移。例如如果状态机中定义了只能从 未指派 (unsigned) 到 已指派 (signed) 的状态流转那么如果你尝试从 执行中 (executing) 到 已指派 (signed) 的转移状态机应该阻止该转移。
示例 java
Transit(from unsigned, to signed, on ASSIGN_SIGNED)
这里from unsigned 和 to signed 表示只有在状态是 unsigned 时事件 ASSIGN_SIGNED 才能触发状态从 unsigned 到 signed 的转移。如果状态已经是 signed即使事件 ASSIGN_SIGNED 被触发状态机会拒绝该转移。
2. 事件的路由控制
在复杂的状态机中可能存在多个事件和方法都可以引发相似的状态转换。例如你可能有多个事件如 ASSIGN_EXCUTING可以从不同的源状态如 unsigned 和 signed转换到同一个目标状态如 executing。在这种情况下from 和 to 就起到了关键作用它们有助于确保事件在正确的上下文中被触发并确保事件与状态之间的关系是明确的。
例如 java
Transit(from unsigned, to executing, on ASSIGN_EXCUTING, callMethod assignExcuting) Transit(from signed, to executing, on ASSIGN_EXCUTING, callMethod assignExcuting)
这两个注解表明ASSIGN_EXCUTING 事件可以发生在两种不同的源状态 (unsigned 或 signed) 下转移到相同的目标状态 (executing)。但是实际的状态流转只有在这些源状态下才会发生。因此from 和 to 参数确保了事件和状态之间的明确关系。
3. 帮助调试和日志记录
from 和 to 的状态信息在调试和日志记录中也非常有用。在实际的运行时日志会记录状态机的状态流转包括当前的源状态 (fromState) 和目标状态 (toState)这些信息帮助开发者了解状态机的运行轨迹。
例如在方法中通常会记录每个状态转换的日志 java
log.info(Transitioning from {} to {} via event {}. Context: {}, fromState, toState, event, context);
这种日志信息有助于在问题出现时快速定位问题并排查逻辑错误。
4. 确保不同的状态转换逻辑
from 和 to 不仅帮助确定状态转移是否合法还能在不同的状态之间实现不同的逻辑。例如你可能希望根据当前状态 (fromState) 的不同执行不同的操作或方法。虽然 callMethod 指定了通用的执行方法但你仍然可能希望根据不同的状态执行不同的逻辑。
例如 java
Transit(from unsigned, to signed, on ASSIGN_SIGNED, callMethod assignUnsignedToSigned) Transit(from signed, to executing, on ASSIGN_EXCUTING, callMethod assignSignedToExecuting)
在这个例子中尽管事件 ASSIGN_SIGNED 和 ASSIGN_EXCUTING 看起来可能是类似的动作但它们发生在不同的状态下因此你可能会希望它们触发不同的处理逻辑。from 和 to 的定义确保了在正确的上下文中执行正确的逻辑。
5. 保持代码清晰和可维护
from 和 to 提供了清晰的状态流转图开发者可以从注解中快速了解状态机的行为和状态转换路径。这对于团队协作、文档编写以及代码的长期维护都非常有帮助。
总结
尽管 callMethod 可以直接指定要调用的方法但是 from 和 to 参数在状态机中扮演着不可或缺的角色
状态合法性验证确保状态流转是符合预定义的规则的避免出现不符合逻辑的状态跳跃。路由控制帮助事件在正确的上下文中触发从正确的源状态转换到目标状态。调试与日志记录提供调试信息帮助开发者追踪状态转移的路径。不同状态的逻辑控制根据 from 和 to 确定具体的业务逻辑。
因此from 和 to 并非多余它们在状态机的结构化和规则验证中发挥了重要作用确保状态转移的过程是可控和符合业务逻辑的。
具体如何状态合法性验证
状态合法性验证确保状态流转是符合预定义的规则的避免出现不符合逻辑的状态跳跃。 这个具体如何实现的from代表当前状态这个参数怎么传入的
在状态机的实现中状态合法性验证是确保状态转移符合预定义的规则、避免非法的状态跳跃的关键。具体来说from 代表当前的状态to 代表目标状态验证这两个状态的合法转移可以通过一系列的机制来实现。
1. from 代表当前状态to 代表目标状态
from表示当前的状态即事件触发时所处的状态。to表示目标状态即状态转换后将进入的状态。
状态合法性验证的核心任务就是在事件发生时检查当前状态from和目标状态to是否符合预定义的合法转换规则。如果不合法状态机应该拒绝该转换并抛出异常或返回错误。
2. 如何实现状态合法性验证
实现状态合法性验证的方式可以分为几种不同的状态机框架或自定义实现可能会有不同的方法。以下是常见的几种实现方式
2.1. 手动映射与检查
一种最简单的实现方式是手动维护一个合法的状态转换表在处理事件时检查当前状态和目标状态是否允许转换。
例如
使用一个状态转换表来存储所有合法的 from - to 映射。当事件发生时根据当前状态from和目标状态to查表检查转换是否合法。
假设我们有如下状态和状态转换表 java
enum State { UNSIGNED, SIGNED, EXECUTING, COMPLETED } MapState, SetState validTransitions new HashMap(); validTransitions.put(State.UNSIGNED, new HashSet(Arrays.asList(State.SIGNED))); validTransitions.put(State.SIGNED, new HashSet(Arrays.asList(State.EXECUTING))); validTransitions.put(State.EXECUTING, new HashSet(Arrays.asList(State.COMPLETED)));
当事件触发时我们可以检查状态是否合法 java
public boolean isValidTransition(State fromState, State toState) { SetState validToStates validTransitions.get(fromState); return validToStates ! null validToStates.contains(toState); }
在状态转移时isValidTransition 方法就会验证 from 和 to 是否匹配预定义的合法转换。
2.2. 通过注解与反射动态绑定
在使用注解驱动的状态机框架中状态转移规则通常通过注解如 Transit来定义。状态机会通过反射机制读取这些注解并验证事件发生时的状态转移是否合法。
例如在基于注解的状态机实现中可能会有如下的代码 java
Transit(from UNSIGNED, to SIGNED, on ASSIGN_SIGNED) Transit(from SIGNED, to EXECUTING, on ASSIGN_EXECUTING)
在处理事件时框架会根据注解定义的 from 和 to 来验证当前状态和目标状态是否匹配。可以通过以下方式实现
读取注解通过反射获取方法上的注解提取出 from 和 to 状态。检查合法性比对当前状态与目标状态是否符合注解中定义的合法状态流转。
假设我们有一个 StateMachine 类在事件发生时我们通过反射查找匹配的转移规则 java
public void handleEvent(String event, State currentState) throws IllegalStateException { // 获取所有标注了 Transit 注解的方法 Method[] methods StateMachine.class.getDeclaredMethods(); for (Method method : methods) { if (method.isAnnotationPresent(Transit.class)) { Transit transit method.getAnnotation(Transit.class); if (transit.from().equals(currentState.name()) transit.on().equals(event)) { // 验证目标状态是否合法 if (validTransitions(currentState, transit.to())) { // 执行状态转换方法 method.invoke(this); } else { throw new IllegalStateException(Invalid state transition from currentState to transit.to()); } } } } }
在这种方式下from 和 to 都是通过注解定义的在事件处理时框架会动态检查当前状态和目标状态是否符合合法转移规则。
2.3. 状态机框架中的自动检查
一些状态机框架如 Spring State Machine、Akka FSM 等已经内建了状态转移规则的验证机制。它们通过状态机的图结构自动验证 from 和 to 之间的合法性开发者只需要通过配置或者注解来定义状态转移而框架会在运行时执行验证。
例如Spring State Machine 提供了一些 API 来配置状态转换 java
StateMachineState, Event stateMachine new StateMachineBuilder.BuilderState, Event() .configure() .withStates() .initial(State.UNSIGNED) .state(State.SIGNED) .state(State.EXECUTING) .state(State.COMPLETED) .and() .withTransitions() .between(State.UNSIGNED, State.SIGNED).perform(assignSigned()) .between(State.SIGNED, State.EXECUTING).perform(assignExecuting()) .between(State.EXECUTING, State.COMPLETED).perform(assignCompleted()) .and() .build();
在这里框架会在 StateMachine 被激活后自动检查每个状态转移是否合法。
3. from 参数如何传入
from 代表当前状态它通常是从当前的 状态机实例 中获取的。具体来说
如果状态机是基于事件驱动的那么 from 状态通常是触发事件时状态机当前的状态。在基于注解的状态机中from 状态会在处理事件时动态传入。在手动配置的状态机中from 状态会随着事件的触发而改变通常由当前的 state 属性表示。
例如在事件处理方法中from 通常是方法的参数或者是类中的实例变量 java
public void handleEvent(State currentState, Event event) { // 当前状态currentState if (isValidTransition(currentState, event)) { // 执行状态转移 } }
在注解驱动的框架中from 可能会自动由框架通过反射从注解中获取或者从事件的上下文中获取当前状态。
4. 总结
状态合法性验证的关键是在事件触发时检查当前状态from和目标状态to是否符合预定义的合法转换规则。具体实现可以通过手动维护转换表、反射检查注解或使用状态机框架的自动验证来实现。通过这些方法我们能够确保状态机的状态流转始终是符合业务逻辑的并避免发生不符合规则的状态跳跃。 状态合法性校验实现例子
触发点方法执行前 /*** 事件触发之前被调用** param fromState* param toState* param event* param context*/Overrideprotected void beforeActionInvoked(Object fromState, Object toState, Object event, Object context) {log.info(LOG_PRE, Thread.currentThread().getStackTrace()[1].getMethodName(), ((DPContext) context).getOrderNumber(), fromState, toState, event, context);/*** 状态合理性校验*/DPContext dpContext (DPContext) context;if (!dpContext.isReentrantLock()) {//重入锁不需要状态合理性校验DPEventEnum dpEventEnum (DPEventEnum) event;((TaskStatusTriggerService) dpContext.getIStatusService()).checkFromState(fromState, toState, context, dpEventEnum);}} public void checkFromState(DPStateEnum dpStateEnum_from, DPStateEnum dpStateEnum_to, DPContext dpContext, DPEventEnum eventEnum) {
// from statusgetInitialState(dpContext.getEvent(), Optional.ofNullable(dpContext.getDpTaskStatusChangeReqDTO()).map(dpTaskStatusChangeReqDTO - dpTaskStatusChangeReqDTO.getWayBill()).orElse(), dpContext);if (!dpContext.getInitialState().equals(dpStateEnum_from)) {log.error(状态异常);throw new YlTaskException(ErrConstant.BUSI_RETURN_ERR, 状态异常);}// to status//幂等性处理if (Arrays.asList(DPEventEnum.CANCEL).contains(eventEnum)) {String taskStatus_db ttTask.getTaskStatus();if (taskStatus_db.equals(dpStateEnum_to.getStatusCode())) {log.warn(当前运单已处理);dpContext.setIdempotent(true);return;}}}