狀態(tài)機配置
狀態(tài)機配置有兩種方式润脸,
- 創(chuàng)建config類抄邀,實現(xiàn)StateMachineConfigurer(或者根據(jù)S\E的不同暗赶,直接繼承其子類StateMachineConfigurerAdapter、EnumStateMachineConfigurerAdapter)傅物,然后分別重寫其不同的configure方法,用于指定對應配置琉预。
- 依然實現(xiàn)StateMachineConfigurer(或繼承其子類)董饰,不過通過StateMachineBuilder.<States, Events>builder()來指定對應配置。
我更傾向于用第二種方式,可以自定義不同的builder卒暂,以服務于不同的業(yè)務場景贮缅,通過顯式指定那個builder的方式來選擇對應的業(yè)務狀態(tài)機配置。
自定義接口
自定義了一個Builder接口介却,用于規(guī)范定義不同業(yè)務的狀態(tài)機配置谴供。
import org.springframework.beans.factory.BeanFactory;
import org.springframework.statemachine.StateMachine;
/**
* 狀態(tài)機構(gòu)造器定義
*/
public interface BizOrderStateMachineBuilder {
String getName();
StateMachine<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> build(BeanFactory beanFactory) throws Exception;
// 業(yè)務一對應的builder name
String WYLOAN_BUILDER_NAME = "wyLoanStateMachineBuilder";
// 業(yè)務二對應的builder name
String VPAY_BUILDER_NAME = "vpayStateMachineBuilder";
}
對應的設置業(yè)務狀態(tài)機配置Builder,注意這里不需要@EnableStateMachine注解齿坷,不是springboot環(huán)境:
@Component
@Slf4j
public class WYLoanBizOrderStateMachineBuilder extends EnumStateMachineConfigurerAdapter implements BizOrderStateMachineBuilder {
......
@Override
public String getName() {
return WYLOAN_BUILDER_NAME;
}
@Override
public StateMachine<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> build(BeanFactory beanFactory) throws Exception {
StateMachineBuilder.Builder<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> builder = StateMachineBuilder.builder();
builder.configureConfiguration()
.withConfiguration()
.autoStartup(true)
.beanFactory(beanFactory)
.machineId("WYLoanStateMachineId");
// 初始化狀態(tài)機桂肌,并指定狀態(tài)集合
// 詳細說明下,由于XXX將用戶實名+申請額度的流程都統(tǒng)一承載在訂單維度永淌,所以這里有個分支流程處理相關數(shù)據(jù)
// 包括實名崎场、業(yè)務審核、資料補全遂蛀、證件上傳谭跨、貸前額度審核等節(jié)點
// 這塊流程與訂單流程全都耦合在一起,拆出來工作量及代價都比較大李滴,所以在訂單系統(tǒng)中統(tǒng)一維護起來
// 故XXX的業(yè)務狀態(tài)最多螃宙,也最復雜
builder.configureStates()
.withStates()
.initial(CREATE)
.choice(WYD_INITIAL_JUMP)
.choice(CHECK_COMPLEMENT)
.choice(CHECK_UPLOAD)
.choice(IN_DEAL_RISK_AUDITING)
.choice(REPAYING) // 還款ing 對應的不同結(jié)果
.end(CANCEL)
.end(CLOSE)
.end(SUCCESS)
.states(EnumSet.allOf(BizOrderStatusEnum.class)) // 所有狀態(tài),避免有遺漏
;
// 指定狀態(tài)機有哪些節(jié)點所坯,即遷移動作
builder.configureTransitions()
// XXX的創(chuàng)建谆扎,并不是CREATE狀態(tài),而是為待實名WAIT_REAL_NAME_AUTH或者待借款WAIT_BORROW狀態(tài)芹助,
// 所以需要虛擬節(jié)點堂湖,自己跳轉(zhuǎn)
.withExternal()
.source(CREATE)
.target(WYD_INITIAL_JUMP)
.event(BizOrderStatusChangeEventEnum.EVT_CREATE)
.action(orderCreateAction, errorHandlerAction)
.and()
.withChoice()
.source(WYD_INITIAL_JUMP)
.first(WAIT_REAL_NAME_AUTH, needNameAuthGurad(), needNameAuthAction)
.then(WAIT_BORROW, toWaitBorrowGuard(), waitBorrowAction)
.last(CREATE)
/** 待實名WAIT_REAL_NAME_AUTH 可以到達的節(jié)點 **/
// cancel
.and().withExternal()
.source(WAIT_REAL_NAME_AUTH)
.target(CANCEL)
.event(EVT_CANCEL)
.action(cancelAction, errorHandlerAction)
// close
.and().withExternal()
.source(WAIT_REAL_NAME_AUTH)
.target(CLOSE)
.event(EVT_SYS_CLOSE)
.action(closeAction, errorHandlerAction)
// 實名,下一步是待hr審核
.and().withExternal()
.source(WAIT_REAL_NAME_AUTH)
.target(WAIT_BIZ_AUDIT)
.event(EVT_NAME_AUTH)
.action(nameAuthAction, errorHandlerAction)
/** 待BIZ審核可到達的節(jié)點 **/
// 關閉
.and().withExternal()
.source(WAIT_BIZ_AUDIT)
.target(CLOSE)
.event(EVT_REFUSE).guard(toCloseGuard())
.action(closeAction, errorHandlerAction)
// BIZ審核通過状土,到待補全資料
.and().withExternal()
.source(WAIT_BIZ_AUDIT)
.target(WAIT_COMPLEMENT)
.event(EVT_AUDIT)
.action(hrAuditAction, errorHandlerAction)
/** 補全資料可以到達的節(jié)點 **/
// 待上傳證件
.and().withExternal()
.source(WAIT_COMPLEMENT)
.target(CHECK_COMPLEMENT)
.event(EVT_COMPLEMENT)
// choice
.and().withChoice()
.source(CHECK_COMPLEMENT)
.first(WAIT_COMPLEMENT, retryCompleteGuard(), retryCompleteAction)
.last(WAIT_UPLOAD_IMG, completeAction)
/** 上傳證件可以到達的節(jié)點 **/
.and().withExternal()
.source(WAIT_UPLOAD_IMG)
.target(CHECK_UPLOAD)
.event(EVT_UPLOAD_IMG)
.and().withChoice()
.source(CHECK_UPLOAD)
.first(WAIT_UPLOAD_IMG, retryUploadGuard(), retryUploadAction)
.last(WAIT_BEF_DEAL_RISK_AUDIT, uploadAction)
/** 貸前審核可以到達的節(jié)點 **/
// 關單
.and().withExternal()
.source(WAIT_BEF_DEAL_RISK_AUDIT)
.target(CLOSE)
.event(EVT_AUDIT)
.guard(toCloseGuard())
.action(closeAction, errorHandlerAction)
// 跳轉(zhuǎn)到待借款
.and().withExternal()
.source(WAIT_BEF_DEAL_RISK_AUDIT)
.target(WAIT_BORROW)
.event(EVT_AUDIT)
.guard(toWaitBorrowGuard())
.action(befDealRiskAction, errorHandlerAction)
/** 待借款可以到達的節(jié)點 **/
// 簽約環(huán)節(jié)補充所有待完善數(shù)據(jù)无蜂,所以是從createService中發(fā)起此流程
.and().withExternal()
.source(WAIT_BORROW)
.target(SIGNED)
.event(EVT_SIGN)
.action(signAction, errorHandlerAction)
.and().withExternal()
.source(WAIT_BORROW)
.target(IN_DEAL_RISK_AUDITING)
.event(EVT_AUDIT)
.and().withChoice()
.source(IN_DEAL_RISK_AUDITING)
.first(CLOSE, toCloseGuard(), closeAction)
.last(WAIT_SIGN, toWaitSignAction)
.and().withExternal()
.source(WAIT_SIGN)
.target(SIGNED)
.event(EVT_SIGN)
.action(signAction, errorHandlerAction)// -- to be complete
/** 簽約可以到達的節(jié)點 **/
.and().withExternal()
.source(SIGNED)
.target(LOANING)
.event(EVT_LOAN)
.action(loanAction, errorHandlerAction)
/* 需要外部觸發(fā),暫時不用choice了蒙谓,無法自己內(nèi)部決定
.and().withChoice()
.source(LOANING)
.first(CLOSE, loanFailGuard(), closeAction)
.last(LOANED, loanSuccGuard(), loanAction())*/
.and().withExternal()
.source(LOANING)
.target(CLOSE)
.event(EVT_LOAN_FAILED)
.action(closeAction, errorHandlerAction)
.and().withExternal()
.source(LOANING)
.target(LOANED)
.event(EVT_LOAN_SUCC)
.action(loanSuccAction, errorHandlerAction)
/** 放款成功可以到達的節(jié)點 **/
.and().withExternal()
.source(LOANED)
.target(BILL_GEN)
.event(EVT_GEN_BILL)
.action(genBillAction, errorHandlerAction)
/** 生成賬單 到逾期/還款 **/
.and().withExternal()
.source(BILL_GEN)
.target(OVERDUE)
.event(EVT_OVERDUE)
.action(overdueAction, errorHandlerAction)
.and().withExternal()
.source(BILL_GEN)
.target(REPAYING)
.event(EVT_REPAY)
// OVERDUE可以到達的節(jié)點
.and().withExternal()
.source(OVERDUE)
.target(REPAYING)
.event(EVT_REPAY)
.and().withExternal()
.source(PART_REPAID)
.target(OVERDUE)
.event(EVT_OVERDUE)
.action(overdueAction, errorHandlerAction)
.and().withExternal()
.source(PART_REPAID)
.target(REPAYING)
.event(EVT_REPAY)
// 還款過程斥季,repaying可以到達的節(jié)點
.and().withChoice()
.source(REPAYING)
.first(PART_REPAID, partRepayGuard(), partRepayAction) // 部分還款,到本身彼乌,狀態(tài)不變
.last(REPAID, repaidAction) // 全部還款
// repayed 可以到達的節(jié)點-success 銷賬
.and().withExternal()
.source(REPAID)
.target(SUCCESS)
.event(EVT_TOSUCCESS)
.action(successAction, errorHandlerAction)
;
return builder.build();
}
......
}
這里先忽略對應的guard及action泻肯,主要關注每個節(jié)點的配置(withXX\source\target\event)渊迁,對照上文中的狀態(tài)變遷圖慰照,理解這套配置。
創(chuàng)建狀態(tài)機引擎的工廠
這里封裝了調(diào)用builder生成對應狀態(tài)機的實現(xiàn)琉朽,如下所示
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.vipfins.finance.middleplatform.order.statemachine.BizOrderStateMachineBuilder.WYLOAN_BUILDER_NAME;
@Component
public class BizOrderStateMachineBuildFactory implements InitializingBean {
@Autowired
private List<BizOrderStateMachineBuilder> builders;
@Autowired
private BeanFactory beanFactory;
/**
* 用來存儲builder-name及builder的map
*/
private Map<String, BizOrderStateMachineBuilder> builderMap = Maps.newConcurrentMap();
/**
* 用于存儲bizType+subBizType 與 builder-name的集合
*/
private Map<String, String> bizTypeBuilderMap = Maps.newConcurrentMap();
/**
* State machine instantiation is a relatively expensive operation so it is better to try to pool instances
* instead of instantiating a new instance with every request
* <p>
* 不過目前先繼續(xù)每次請求過來進行創(chuàng)建毒租,后續(xù)再考慮池化操作
* <p>
* 創(chuàng)建statemachine
*
* @param bizType
* @param subBizType
* @return
*/
public StateMachine<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> createStateMachine(String bizType, String subBizType) {
if (StringUtils.isBlank(subBizType)) {
subBizType = "";
}
String key = StringUtils.trim(bizType) + StringUtils.trim(subBizType);
String builderName = bizTypeBuilderMap.get(key);
if (StringUtils.isBlank(builderName)) {
throw new BusinessException(BizOrderErrorCode.NO_CORRESPONDING_STATEMACHINE_BUILDER, "當前業(yè)務沒有對應的狀態(tài)機配置,請檢查");
}
return createStateMachine(builderName);
}
/**
* 創(chuàng)建stateMachine
* @param builderName
* @return
*/
public StateMachine<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> createStateMachine(String builderName) {
BizOrderStateMachineBuilder builder = builderMap.get(builderName);
StateMachine<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> stateMachine = null;
try {
stateMachine = builder.build(beanFactory);
} catch (Exception e) {
e.printStackTrace();
throw new BusinessException(BizOrderErrorCode.ORDER_GENERIC_EXCEPTION, e.getLocalizedMessage());
}
return stateMachine;
}
/**
* Invoked by a BeanFactory after it has set all bean properties supplied
* (and satisfied BeanFactoryAware and ApplicationContextAware).
* <p>This method allows the bean instance to perform initialization only
* possible when all bean properties have been set and to throw an
* exception in the event of misconfiguration.
*
* @throws Exception in the event of misconfiguration (such
* as failure to set an essential property) or if initialization fails.
*/
@Override
public void afterPropertiesSet() throws Exception {
builderMap = builders.stream().collect(Collectors.toMap(
BizOrderStateMachineBuilder::getName,
Function.identity()
));
// 暫時將bizType和subBizType XXX-單筆授信作為key,綁定對應的XXX狀態(tài)機墅垮,后續(xù)還需要綁定別的業(yè)務
bizTypeBuilderMap.put(BizOrderBizTypeEnum.EMPLOAN.getOrderBizType() + BizOrderSubTypeEnum.SINGLE_AUTH.getBizSubType(),
WYLOAN_BUILDER_NAME);
// XXX 不區(qū)分子業(yè)務類型
bizTypeBuilderMap.put(BizOrderBizTypeEnum.EMPLOAN.getOrderBizType(), WYLOAN_BUILDER_NAME);
}
}
外部調(diào)用時惕医,只需要使用createStateMachine就可以創(chuàng)建出對應的狀態(tài)機實例。
Guard相關實現(xiàn)
上文中算色,每次choice都有至少一個guard出現(xiàn)抬伺,但是其實在action之前也可以指定guard,如果不滿足guard中運行的條件(guard返回false)灾梦,就不會執(zhí)行對應的action峡钓。這里忽略了這個配置。
上面配置中對應的guard實現(xiàn)(依然在WYLoanBizOrderStateMachineBuilder中):
/**
* 判斷是否要到待借款狀態(tài)
*
* @return 如果需要若河,返回true能岩,否則返回false
*/
private Guard<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> toWaitBorrowGuard() {
return context -> {
String finalOrderStatus = (String) context.getMessageHeader(BizOrderConstants.FINAL_STATUS_KEY);
if (BizOrderStatusEnum.equals(finalOrderStatus, BizOrderStatusEnum.WAIT_BORROW)) {
log.debug("toWaitBorrowGurad return true");
return true;
}
log.debug("toWaitBorrowGurad return false");
return false;
};
}
/**
* 判斷是否需要用戶實名
*
* @return 如果需要,返回true萧福,否則返回false
*/
private Guard<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> needNameAuthGurad() {
return context -> {
String finalOrderStatus = (String) context.getMessageHeader(BizOrderConstants.FINAL_STATUS_KEY);
if (BizOrderStatusEnum.equals(finalOrderStatus, BizOrderStatusEnum.WAIT_REAL_NAME_AUTH)) {
log.debug("needNameAuthGurad return true");
return true;
}
log.debug("needNameAuthGurad return false");
return false;
};
}
private Guard<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> retryUploadGuard() {
return context -> {
// 判斷請求參數(shù)中的targetStatus是否為需要重試upload
String finalOrderStatus = (String) context.getMessageHeader(BizOrderConstants.FINAL_STATUS_KEY);
if (BizOrderStatusEnum.equals(finalOrderStatus, BizOrderStatusEnum.WAIT_UPLOAD_IMG)) {
log.debug("retryUploadGuard return true");
return true;
}
log.debug("retryUploadGuard return false");
return false;
};
}
/**
* 判斷是否需要重試補全資料
*
* @return 結(jié)果
*/
private Guard<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> retryCompleteGuard() {
return context -> {
// 判斷請求參數(shù)中的targetStatus是否為需要重試complete補全
String finalOrderStatus = (String) context.getMessageHeader(BizOrderConstants.FINAL_STATUS_KEY);
if (BizOrderStatusEnum.equals(finalOrderStatus, BizOrderStatusEnum.WAIT_COMPLEMENT)) {
log.debug("retryCompleteGuard return true");
return true;
}
log.debug("retryCompleteGuard return false");
return false;
};
}
private Guard<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> toCloseGuard() {
return context -> {
// 判斷請求參數(shù)中的targetStatus是否為關單
String finalOrderStatus = (String) context.getMessageHeader(BizOrderConstants.FINAL_STATUS_KEY);
if (BizOrderStatusEnum.equals(finalOrderStatus, BizOrderStatusEnum.CLOSE)) {
log.debug("toCloseGuard return true");
return true;
}
log.debug("toCloseGuard return false");
return false;
};
}
private Guard<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> partRepayGuard() {
return context -> {
// 判斷請求參數(shù)中的targetStatus是否為關單
String finalOrderStatus = (String) context.getMessageHeader(BizOrderConstants.FINAL_STATUS_KEY);
if (BizOrderStatusEnum.equals(finalOrderStatus, BizOrderStatusEnum.PART_REPAID)) {
log.debug("partRepayGuard return true");
return true;
}
log.debug("partRepayGuard return false");
return false;
};
}
注意拉鹃,每個guard都從messageHeader中獲取了FINAL_STATUS_KEY對應的值,這個數(shù)據(jù)是由外部系統(tǒng)傳入鲫忍,然后在每次調(diào)用狀態(tài)機時設置到message中膏燕,外部調(diào)用如下:
Message<BizOrderStatusChangeEventEnum> eventMsg = MessageBuilder.withPayload(eventEnum)
// key 與 status change 時不同,對應的model也不同
.setHeader(BizOrderConstants.BIZORDER_CONTEXT_CREATE_KEY, bizOrderCreateRequest)
// 根據(jù)傳遞過來的訂單狀態(tài)決定后續(xù)choice跳轉(zhuǎn)
.setHeader(BizOrderConstants.FINAL_STATUS_KEY, bizOrderCreateRequest.getBizOrderCreateModel().getOrderStatus())
.build();
sendResult = stateMachine.sendEvent(eventMsg);
這里這么實現(xiàn)的原因是悟民,目前的訂單系統(tǒng)沒辦法自己判斷某個條件是否達成煌寇,只能依賴外部參數(shù)傳入。但是如果訂單系統(tǒng)中可以通過調(diào)用外部服務做最終判斷逾雄,這里guard的實現(xiàn)就可以系統(tǒng)自己判斷阀溶,而不是依賴外部參數(shù)傳入。
Action注入
配置中除了guard之外鸦泳,另一個跟業(yè)務實現(xiàn)緊密關聯(lián)的就是Action了银锻,下面將所有的Action注入的代碼羅列如下(注入到WYLoanBizOrderStateMachineBuilder中)
@Autowired
@Qualifier("errorHandlerAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> errorHandlerAction;
@Resource(name = "orderCreateAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> orderCreateAction;
@Resource(name = "successAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> successAction;
@Resource(name = "cancelAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> cancelAction;
@Resource(name = "closeAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> closeAction;
@Resource(name = "nameAuthAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> nameAuthAction;
@Resource(name = "needNameAuthAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> needNameAuthAction;
@Resource(name = "waitBorrowAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> waitBorrowAction;
@Resource(name = "hrAuditAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> hrAuditAction;
@Resource(name = "retryCompleteAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> retryCompleteAction;
@Resource(name = "completeAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> completeAction;
@Resource(name = "retryUploadAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> retryUploadAction;
@Resource(name = "uploadAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> uploadAction;
@Resource(name = "befDealRiskAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> befDealRiskAction;
// sign時需要補充所有必需業(yè)務數(shù)據(jù)
@Resource(name = "signAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> signAction;
@Resource(name = "toWaitSignAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> toWaitSignAction;
@Resource(name = "loanAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> loanAction;
@Resource(name = "loanSuccAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> loanSuccAction;
@Resource(name = "genBillAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> genBillAction;
@Resource(name = "overdueAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> overdueAction;
@Resource(name = "partRepayAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> partRepayAction;
@Resource(name = "repaidAction")
private Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> repaidAction;
@Autowired默認注入byType,@Qualifier指定對應的beanName做鹰,所以二者結(jié)合起來等同于@Resource的作用击纬。
Action實現(xiàn)
首先注意errorHandlerAction,這里并沒有什么業(yè)務邏輯,只是封裝了異常發(fā)生時的信息钾麸,實現(xiàn)如下:
/**
* 異常處理Action
*
* @return action對象
*/
@Bean(name = "errorHandlerAction", autowire = Autowire.BY_TYPE)
public Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> errorHandlerAction() {
return context -> {
RuntimeException exception = (RuntimeException) context.getException();
log.error("stateMachine execute error = ", exception);
context.getStateMachine()
.getExtendedState().getVariables()
.put(RuntimeException.class, exception);
};
}
這里將發(fā)生的異常信息記錄在StateMachineContext中更振,在外部可以根據(jù)這個這個值是否存在來判斷是否有異常發(fā)生。
其他的Action實現(xiàn)大同小異:
- 從context中獲取狀態(tài)機
- 從context中獲取請求參數(shù)
- 打印日志饭尝,記錄狀態(tài)機信息肯腕、請求參數(shù)信息
- 通過注入的bizManager實現(xiàn)來處理具體的業(yè)務邏輯,關于bizManager钥平,可以參考http://www.reibang.com/p/ba744cfd3672文章中BaseBizManager的定義实撒,以及其子類AbstractBizManagerImpl的實現(xiàn)
以訂單創(chuàng)建和訂單待關閉兩個Action為例,其對應代碼實現(xiàn)如下:
/**
* 創(chuàng)建訂單
* @return
*/
@Bean(name = "orderCreateAction", autowire = Autowire.BY_TYPE)
public Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> orderCreateAction(){
return context -> {
// 訂單創(chuàng)建相關請求
BizOrderCreateRequest createRequest = (BizOrderCreateRequest) context.getMessageHeader(BizOrderConstants.BIZORDER_CONTEXT_CREATE_KEY);
// 從context中獲取狀態(tài)機
StateMachine<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> stateMachine = context.getStateMachine();
log.info("order info={},stateMachine id={},uuid={},jump from {} to sign status",
createRequest,
stateMachine.getId(),
stateMachine.getUuid(),
stateMachine.getState().getId());
bizOrderCreateBizManager.process(createRequest);
};
}
/**
* 自動跳轉(zhuǎn)到close的Action
* <p>
* 比如超時未處理,希望關單知态,可以使用此action
*
* @return action對象
*/
@Bean(name = "toCloseAction",autowire = Autowire.BY_TYPE)
public Action<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> toCloseAction() {
return context -> {
StateMachine<BizOrderStatusEnum, BizOrderStatusChangeEventEnum> stateMachine = context.getStateMachine();
BizOrderStatusRequest statusRequest = (BizOrderStatusRequest) context.getMessageHeader(BizOrderConstants.BIZORDER_CONTEXT_KEY);
log.info("order info={},stateMachine id={},uuid={}, jump from {} to toClose status",
statusRequest,
stateMachine.getId(),
stateMachine.getUuid(),
stateMachine.getState().getId());
bizOrderToCloseBizManager.process(statusRequest);
};
}
相當于action只是一層粘連捷兰,而具體的實現(xiàn)則落地在bizManager中。
下一章節(jié)會展開BizManager的實現(xiàn)负敏。