Spring StateMachine(2) UML狀態圖支援
阿新 • • 發佈:2019-01-10
還是剛才的以二級審批請假流程為例。
繪製流程
首先建立 Papyrus 專案,選擇 StateMachine 模板,繪製流程圖如下:
然後建立 6 個 signal event 和與之繫結的 signal :
注意,在 Papyrus 圖中,除了 State (狀態) 和 Transition(遷移)之外,還有 Signal 和 Signal Event 的概念,它們對應於 StateMachine 中的 Event(事件)。其中 Signal 就是事件的名字(字串常量)。
將 Tansition 和 Signal Event 繫結(設定 trigger)。
載入 uml 狀態圖
將 Papyrus 生成的 uml 檔案放到 idea 的 resource 目錄。
因為 State、Event 和 Transition 都定義在 UML 中了,所以 States 列舉和 Events 列舉不再需要,狀態機的配置也簡化了,直接從 UML 檔案來載入:
@Override public void configure(StateMachineModelConfigurer<String, String> model) throws Exception { model .withModel() .factory(modelFactory()); } @Bean public StateMachineModelFactory<String, String> modelFactory() { // 測試二級審批請假流程 UmlStateMachineModelFactory factory = new UmlStateMachineModelFactory( "classpath:model.uml"); factory.setStateMachineComponentResolver(stateMachineComponentResolver()); return factory; }
注意,這裡 States 和 Events 的型別都變成了 String,畢竟在 UML 中不太好定義型別。
如果要註冊 Action 或者 Guard,可以通過 Resolver 進行:
@Bean public StateMachineComponentResolver<String, String> stateMachineComponentResolver() { DefaultStateMachineComponentResolver<String, String> resolver = new DefaultStateMachineComponentResolver<>(); resolver.registerAction("myAction", myAction()); resolver.registerGuard("myGuard", myGuard()); return resolver; } public Action<String, String> myAction() { return new Action<String, String>() { @Override public void execute(StateContext<String, String> context) { } }; } public Guard<String, String> myGuard() { return new Guard<String, String>() { @Override public boolean evaluate(StateContext<String, String> context) { return false; } }; }
傳送事件
跟之前一樣,傳送事件使用狀態機的 sendEvent。只不過 Event 的型別統統是字串,而且必須在 UML 中定義為 Signal。
private BaseResponse sendEvent(String event,String leaveId){
BaseResponse result = new BaseResponse();
if(leaveId == null || leaveId.length()==0){
result.success = false;
result.message = "leaveId 不能為空";
return result;
}
try {
// 根據業務 id 獲取狀態
persister.restore(stateMachine,leaveId);
result.success = stateMachine.sendEvent(event);
// 持久化狀態機
if (result.success) {
persister.persist(stateMachine, leaveId);
}
JSONObject data = new JSONObject();
result.message = result.success ? "執行成功":"執行失敗";
result.message = result.message + ",當前狀態為:"+stateMachine.getState().getId();
data.put("leaveId",leaveId);
data.put("event",event);
data.put("state",stateMachine.getState().getId());
result.data = data;
} catch (Exception e) {
e.printStackTrace();
result.message = e.getMessage();
}finally {
stateMachine.stop();
return result;
}
}
結論
可以看到,通過 UML 方式繪製狀態機,減少了在程式碼中定義 Event、State 和 Transition 的過程,但 UML 中必須通過額外的元素(Signal和 Signal Event)來定義事件,在目前來說 Spring StateMachine 只支援 Papyrus 繪製的 UML 圖。