可乐 状态机组件,状态流转 清晰明了
SEC 封装
SEC 为 Status,Event,Context 首字母缩写。
员工请假 SEC 封装
请假大概包含3个领域模型,员工(搬砖员工,领导,HR)/请假单/请假单操作明细,此处省略模型CRUD。
@Getter
@AllArgsConstructor
public enum LeaveStatus {
LEAVE_SUBMIT(1, "已申请"),
LEADER_AUDIT_PASS(2, "领导审批通过"),
LEADER_AUDIT_REFUSE(3, "领导审批拒绝"),
HR_PASS(4, "HR审批通过"),
HR_REFUSE(5, "HR审批拒绝"),
END(6, "END");
private final Integer code;
private final String desc;
}
@Getter
@AllArgsConstructor
public enum LeaveEvent {
EMPLOYEE_SUBMIT("提交请假单"),
LEADER_AUDIT("领导审批"),
HR_AUDIT("HR审批");
private final String desc;
}
@EqualsAndHashCode(callSuper = false)
@Data
public class LeaveContextCmd extends Command {
private AgreeOrDisagree agreeOrDisagree;
private String reason;
private String remarks;
}
@Getter
@AllArgsConstructor
public enum AgreeOrDisagree {
AGREE(0, "同意"),
DISAGREE(1, "拒绝");
private final Integer code;
private final String desc;
}
服务和状态流转定义
public interface LeaveService {
String STATE_MACHINE_ID = "leaveStateMachineId";
default Condition<LeaveContextCmd> checkIfPass() {
return (ctx) -> ctx.getAgreeOrDisagree() == AgreeOrDisagree.AGREE;
}
default Condition<LeaveContextCmd> checkIfNotPass() {
return (ctx) -> ctx.getAgreeOrDisagree() == AgreeOrDisagree.DISAGREE;
}
Action<LeaveStatus, LeaveEvent, LeaveContextCmd> employeeSubmitAction();
LeaveStatus employeeLeave(LeaveContextCmd leaveContextCmd);
Action<LeaveStatus, LeaveEvent, LeaveContextCmd> leaderAuditAction();
LeaveStatus leaderAudit(LeaveContextCmd leaveContextCmd);
Action<LeaveStatus, LeaveEvent, LeaveContextCmd> hrAuditAction();
LeaveStatus hrAudit(LeaveContextCmd leaveContextCmd);
}
@Slf4j
@Service
public class LeaveServiceImpl implements LeaveService {
private StateMachine<LeaveStatus, LeaveEvent, LeaveContextCmd> stateMachine;
@PostConstruct
public void stateMachine() {
log.warn("请假状态流转定义");
StateMachineBuilder<LeaveStatus, LeaveEvent, LeaveContextCmd> stateMachineBuilder = StateMachineBuilderFactory.create();
stateMachineBuilder.internalTransition()
.within(LeaveStatus.LEAVE_SUBMIT)
.on(LeaveEvent.EMPLOYEE_SUBMIT)
.perform(employeeSubmitAction());
stateMachineBuilder.externalTransition()
.from(LeaveStatus.LEAVE_SUBMIT).to(LeaveStatus.LEADER_AUDIT_PASS)
.on(LeaveEvent.LEADER_AUDIT).when(checkIfPass())
.perform(leaderAuditAction());
stateMachineBuilder.externalTransition()
.from(LeaveStatus.LEAVE_SUBMIT).to(LeaveStatus.LEADER_AUDIT_REFUSE)
.on(LeaveEvent.LEADER_AUDIT).when(checkIfNotPass())
.perform(leaderAuditAction());
stateMachineBuilder.externalTransition()
.from(LeaveStatus.LEADER_AUDIT_PASS).to(LeaveStatus.HR_PASS)
.on(LeaveEvent.HR_AUDIT).when(checkIfPass())
.perform(hrAuditAction());
stateMachineBuilder.externalTransition()
.from(LeaveStatus.LEADER_AUDIT_PASS).to(LeaveStatus.HR_REFUSE)
.on(LeaveEvent.HR_AUDIT).when(checkIfNotPass())
.perform(hrAuditAction());
stateMachine = stateMachineBuilder.build(STATE_MACHINE_ID);
}
@Override
public Action<LeaveStatus, LeaveEvent, LeaveContextCmd> employeeSubmitAction() {
return (from, to, leaveEvent, ctx) -> {
log.warn("生成一条员工请假申请单");
log.warn("From:" + from + " To:" + to + " On:" + leaveEvent + " Context:" + ctx);
};
}
@Override
public LeaveStatus employeeLeave(LeaveContextCmd leaveContextCmd) {
return stateMachine.fireEvent(LeaveStatus.LEAVE_SUBMIT, LeaveEvent.EMPLOYEE_SUBMIT, leaveContextCmd);
}
@Override
public Action<LeaveStatus, LeaveEvent, LeaveContextCmd> leaderAuditAction() {
return (from, to, leaveEvent, ctx) -> {
log.warn("更新请假单记录状态");
log.warn("生成一条请假单操作明细数据");
log.warn("From:" + from + " To:" + to + " On:" + leaveEvent + " Context:" + ctx);
};
}
@Override
public LeaveStatus leaderAudit(LeaveContextCmd leaveContextCmd) {
return stateMachine.fireEvent(LeaveStatus.LEAVE_SUBMIT, LeaveEvent.LEADER_AUDIT, leaveContextCmd);
}
@Override
public Action<LeaveStatus, LeaveEvent, LeaveContextCmd> hrAuditAction() {
return (from, to, leaveEvent, ctx) -> {
log.warn("更新请假单记录状态");
log.warn("生成一条请假单操作明细数据");
log.warn("From:" + from + " To:" + to + " On:" + leaveEvent + " Context:" + ctx);
};
}
@Override
public LeaveStatus hrAudit(LeaveContextCmd leaveContextCmd) {
return stateMachine.fireEvent(LeaveStatus.LEADER_AUDIT_PASS, LeaveEvent.HR_AUDIT, leaveContextCmd);
}
}
Controller
@Slf4j
@RestController
public class LeaveController {
@Setter(onMethod_ = {@Autowired})
private LeaveService leaveService;
@PostMapping("/employLeave")
public Response employLeave(@RequestBody LeaveContextCmd leaveContextCmd) {
LeaveStatus leaveStatus = leaveService.employeeLeave(leaveContextCmd);
return SingleResponse.of(leaveStatus);
}
@PostMapping("/leaderAudit")
public Response leaderAudit(@RequestBody LeaveContextCmd leaveContextCmd) {
LeaveStatus leaveStatus = leaveService.leaderAudit(leaveContextCmd);
return SingleResponse.of(leaveStatus);
}
@PostMapping("/hrAudit")
public Response hrAudit(@RequestBody LeaveContextCmd leaveContextCmd) {
LeaveStatus leaveStatus = leaveService.hrAudit(leaveContextCmd);
return SingleResponse.of(leaveStatus);
}
}
构建文件概要
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.alibaba.cola:cola-component-dto'
implementation 'com.alibaba.cola:cola-component-statemachine'