【问题标题】:Implementing State management for a Spring boot application为 Spring Boot 应用程序实现状态管理
【发布时间】:2021-06-10 17:25:21
【问题描述】:

我正在开发一个 Spring boot 应用程序,我需要实现以下格式的状态转换表,其中动作和条件的组合决定了实​​体从一种状态到另一种状态的转换:

From State| To State|   User Action      | Condition
----------------------------------------------------------------
    S0    |   S1    | Create a record    |         
-----------------------------------------------------------------
    S1    |   S1    | Update a record    |         
 -----------------------------------------------------------------
    S1    |   S1    | Run validation     |
 -----------------------------------------------------------------
    S1    |   S2    | Mark state as S2   |  Record is valid

在此应用程序中,已经有 CreateUpdateRunning Validation 的 API。

根据要求,状态机应该是可配置的,以便可以添加任何新状态/删除现有状态,以及可以通过仪表板更改给定转换的操作和条件。

为了满足这一要求,我曾考虑将StateActionConditionStateTransition 视为单独的实体,如下所示:

动作实体:

 @Entity
 @Table(name = "action")
 public class Action implements Serializable {
     @Id
     private String id;

     @Column(name = "action_type")
     @Enumerated(EnumType.STRING)
     private ActionType actionType;

     @Column(name = "action_description")
     private String actionDescription;
 }

动作类型枚举:

Enum ActionType {
   CREATE_RECORD, UPDATE_RECORD, RUN_VALIDATION;
}

国家实体:

 @Entity
 @Table(name = "state")
 public class State implements Serializable {
     @Id
     private String id;

     @Column(name = "name")
     private String name;
 }

条件实体(不明白怎么做)

 @Entity
 @Table(name = "condition")
 public class Condition implements Serializable {
     @Id
     private String id;

     @Column(name = "description")
     private String description;

     ... CANNOT UNDERSTAND WHAT ELSE SHOULD I PUT HERE
 }

状态转换实体如下:

 @Entity
 @Table(name = "state_transition")
 public class State implements Serializable {
     @Id
     private String id;

     @Column(name = "from_state")
     private String fromStateId;

     @Column(name = "to_state")
     private String toStateId;

     @Column(name = "action_id")
     private String actionId;

     @Column(name = "condition_id")
     private String conditionId;
 }

基本上,结合当前状态、动作和条件,我应该能够从状态转换表中找出下一个状态。

但我陷入了以下问题:

  1. 我应该如何实施用户操作?正如我之前提到的,我上面指定的其中一些操作作为 API 存在于应用程序中。基本上,我无法理解如何将我想要实现的用户操作实体与现有流程联系起来。

  2. 我应该如何将 Condition 实现为实体?条件基本上是一个表达式,其计算结果为真/假。我没有得到任何线索,我怎样才能将它作为一个实体来捕获。

任何人都可以就这个问题提供任何指点吗?谢谢。

【问题讨论】:

    标签: spring-boot hibernate jpa state-machine state-management


    【解决方案1】:

    我看不出引入所有这些实体的理由。动作似乎是静态的,即您正在代码中定义可能的动作,那么为什么要为此烦恼并创建一个实体呢?条件只是包含表达式的转换实体中的一个字段。我也不认为你需要有一个专门的国家实体,但这可能是有争议的。总的来说,我建议您将状态机序列化为 JSON,因为无论如何您总是会读取整个状态机。因此,除非您希望能够查询或引用该定义中的专用元素(参照完整性),否则不要将其建模为表。所以要么

     @Entity
     @Table(name = "state_transition")
     public class StateTransition implements Serializable {
         @Id
         private String id;
    
         @Column(name = "from_state")
         private String fromState;
    
         @Column(name = "to_state")
         private String toState;
    
         @Column(name = "action")
         private ActionType action;
    
         @Column(name = "condition")
         private String condition;
     }
    

     @Entity
     @Table(name = "state_machine")
     public class StateMachine implements Serializable {
         @Id
         private String id;
    
         @Column(name = "definition")
         private String definition;
    
     }
    

    然后您可以对定义进行反序列化,甚至可以在 AttributeConverter 中将其反序列化为适合您需要的任何模型。

    【讨论】:

    • @ChristianBelkov,感谢您的回复。实际上,我希望将来可以配置 Condition/Action,用户将能够创建/更新现有的操作、条件。
    • 我不知道您的情况如何,但我希望您为此目的使用表达式语言。我实现了几个这样的系统,在每一个系统中,动作都是静态的,即我必须实现一些东西来添加新动作。我建议您在遇到障碍之前保持简单。
    • @ChristianBelkov,感谢您的回复。当然,我会尽量保持简单。能否请您指点一下您提到的表达式语言?
    • 您可以使用的表达语言有很多。 Jakarta/Java EE 的 UEL(统一表达式语言),SpEL(Spring 表达式语言)。这实际上取决于您希望如何向用户公开这种语言。如果你想公开一种简单的表达式语言,我建议你看看 Blaze-Expression(我是它的创造者)或 JEval。
    猜你喜欢
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    • 2020-05-01
    • 1970-01-01
    • 2017-01-19
    • 2017-01-29
    • 2022-07-13
    • 1970-01-01
    相关资源
    最近更新 更多