背景
传统的MVC架构中,业务逻辑一般在service层实现,但随着业务的发展,service层也在不断充斥、嵌入各种业务逻辑代码,导致service层代码过于臃肿、庞大,不利于代码的维护和业务的后续迭代发展。此时我们需要对service层进行瘦身,以达到职责分离、高内聚低耦合的效果。
下面以注册链路为例,讲述如何通过各种方式,对service层的注册逻辑进行瘦身,简化,从而降低代码复杂度,并达到职责分离的效果。
注册链路实现
我们以用户注册为例,对于用户注册,在业务逻辑方面,依次需要进行下列操作:
- 注册表单数据校验
- 账号冲突定位
- 密码加密处理
- 用户权限处理
- 创建用户
- 下发登录态
service层实现业务逻辑
实现
在传统的MVC架构中,对于注册逻辑,属于业务层逻辑,因此会在service层进行实现,具体实现内容如下:
@Override
public ResultT<String> register(RegisterRequest registerRequest) {
// 注册表单参数校验
checkRegisterForm(registerRequest);
// 账号冲突定位
checkUserConflict(registerRequest);
UserDO userDO = convert2DO(registerRequest);
// 密码加密
richPassword(userDO);
// 权限设置
richRole(userDO);
if (userMapper.insert(userDO) > 0) {
// 创建账号成功,下发登录态
String token = createLoginToken(userDO);
return ResultT.success(token);
}
return ResultT.fail();
}
/**
* 下发登录态
* @param userDO
* @return
*/
private String createLoginToken(UserDO userDO) {
// mock 下发登录态
return UUID.randomUUID().toString();
}
/**
* 权限设置
* @param userDO
*/
private void richRole(UserDO userDO) {
// mock 先使用默认权限
userDO.setRole(UserRoleConstant.DEFAULT_ROLE.toString());
}
/**
* 密码加密
* @param userDO
*/
private void richPassword(UserDO userDO) {
// mock 先不对密码做处理
userDO.setPassword(userDO.getPlainPassword());
}
/**
* 账号冲突校验
* @param registerRequest
*/
private void checkUserConflict(RegisterRequest registerRequest) {
if (StringUtils.isNotEmpty(registerRequest.getLoginId())) {
LambdaQueryWrapper<UserDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserDO::getLoginId, registerRequest.getLoginId());
Integer count = userMapper.selectCount(queryWrapper);
if (count > 0) {
throw new UicException(ErrorCode.USER_CONFLICT_ERROR);
}
}
LambdaQueryWrapper<UserDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserDO::getEmail, registerRequest.getEmail());
Integer count = userMapper.selectCount(queryWrapper);
if (count > 0) {
throw new UicException(ErrorCode.USER_CONFLICT_ERROR);
}
}
/**
* 注册表单参数校验
* @param registerRequest
*/
private void checkRegisterForm(RegisterRequest registerRequest) {
if (StringUtils.isEmpty(registerRequest.getEmail()) || StringUtils.isEmpty(registerRequest.getPassword())) {
throw new UicException(ErrorCode.PARAM_VALIDATE_ERROR);
}
}
private UserDO convert2DO(RegisterRequest registerRequest) {
UserDO userDO = new UserDO();
userDO.setLoginId(registerRequest.getLoginId());
if (StringUtils.isEmpty(userDO.getLoginId())) {
userDO.setLoginId(UUID.randomUUID().toString().replaceAll("-", ""));
}
userDO.setEmail(registerRequest.getEmail());
userDO.setPlainPassword(registerRequest.getPassword());
userDO.setCreateTime(new Date());
userDO.setUpdateTime(new Date());
return userDO;
}
缺点
在上述代码中,将每一个步骤都抽取为对应的方法,思路相对比较清晰,但这建立在业务逻辑相对稳定、简单的前提下,当后续业务逻辑开始改动,比如需要使用md5对密码进行加密、根据入参决定用户权限、通过jwt创建登录态token等等,此时我们虽然能在这些方法的基础上进行修改或新增,但是这些方法后续会越来越大,不利于后续的维护,此外,我们将这些步骤都堆积在service类中,不利于后续的职责分离。
抽象为执行类依次执行
实现
每一个方法对应一个职责,我们通过将这些逻辑,抽取为一个个执行类,并通过枚举将这些执行类的执行顺序进行编排。
交互图如下:
代码实现如下:
首先定义IFlow、IFlowExecutor、IFlowContext,然后定义AbstractFlow抽象类,实现流程执行器的增加、获取
public interface IFlow {
List<IFlowExecutor> getFlowExecutors();
default void execute(IFlowContext iFlowContext) {
List<IFlowExecutor> flowExecutors = getFlowExecutors();
if (CollectionUtils.isEmpty(flowExecutors)) {
return;
}
for (IFlowExecutor flowExecutor : flowExecutors) {
flowExecutor.execute(iFlowContext);
}
}
}
public interface IFlowContext {
}
public interface IFlowExecutor {
void execute(IFlowContext iFlowContext);
}
public abstract class AbstractFlow implements IFlow {
protected List<IFlowExecutor> iFlowExecutorList = new ArrayList<>();
public List<IFlowExecutor> getFlowExecutors() {
return iFlowExecutorList;
}
public void addFlowExecutor(IFlowExecutor executor) {
this.iFlowExecutorList.add(executor);
}
}
然后依次实现表单校验、冲突校验、密码加密、权限设置、创建账号、登录态下发等执行器
@Component
public class BuildUserTokenExecutor implements IFlowExecutor {
@Autowired
private JwtUtils jwtUtils;
@Override
public void execute(IFlowContext iFlowContext) {
RegisterFlowContext registerFlowContext = (RegisterFlowContext) iFlowContext;
UserDO userDO = registerFlowContext.getUserDO();
Map<String, Object> payloads = new HashMap<>();
payloads.put("email", userDO.getEmail());
payloads.put("id", userDO.getId());
payloads.put("loginId", userDO.getLoginId());
payloads.put("role", userDO.getRole());
String token = jwtUtils.encrypt(userDO.getId().toString(), payloads);
registerFlowContext.setToken(token);
}
}
@Component
public class CreateUserExecutor implements IFlowExecutor {
@Autowired
private UserMapper userMapper;
@Override
public void execute(IFlowContext iFlowContext) {
RegisterFlowContext registerFlowContext = (RegisterFlowContext) iFlowContext;
System.out.println(registerFlowContext);
UserDO userDO = new UserDO();
userDO.setLoginId(registerFlowContext.getLoginId());
if (StringUtils.isEmpty(userDO.getLoginId())) {
userDO.setLoginId(UUID.randomUUID().toString().replaceAll("-", ""));
}
userDO.setEmail(registerFlowContext.getEmail());
userDO.setPlainPassword(registerFlowContext.getPassword());
userDO.setPassword(registerFlowContext.getEncryptPassword());
userDO.setRole(registerFlowContext.getRoles());
userDO.setCreateTime(new Date());
userDO.setUpdateTime(new Date());
Map<String, String> featureMap = new HashMap<>();
featureMap.put(UserConstant.ENCRYPT_TYPE, registerFlowContext.getEncryptType());
userDO.setFeatures(FeatureUtils.convert2Feature(featureMap));
// 持久化数据库
int insert = userMapper.insert(userDO);
if (insert <= 0) {
throw new UicException(ErrorCode.PERSISTENCE_DATA_ERROR);
}
registerFlowContext.setUserDO(userDO);
}
}
@Component
public class EncryptPasswordExecutor implements IFlowExecutor {
@Autowired
private EncryptHandlerFactory encryptHandlerFactory;
@Override
public void execute(IFlowContext iFlowContext) {
RegisterFlowContext registerFlowContext = (RegisterFlowContext) iFlowContext;
String encryptType = registerFlowContext.getEncryptType();
if (StringUtils.isEmpty(encryptType)) {
encryptType = EncryptTypeEnum.MD5.getType();
registerFlowContext.setEncryptType(encryptType);
}
IEncryptHandler iEncryptHandler = encryptHandlerFactory.getEncryptHandlerByType(encryptType);
EncryptRequest encryptRequest = new EncryptRequest();
encryptRequest.setPlainText(registerFlowContext.getPassword());
String encryptPassword = iEncryptHandler.encrypt(encryptRequest);
registerFlowContext.setEncryptPassword(encryptPassword);
}
}
@Component
public class RegisterFormCheckExecutor implements IFlowExecutor {
@Override
public void execute(IFlowContext iFlowContext) {
RegisterFlowContext registerFlowContext = (RegisterFlowContext) iFlowContext;
if (StringUtils.isEmpty(registerFlowContext.getEmail())
|| StringUtils.isEmpty(registerFlowContext.getPassword())) {
throw new UicException(ErrorCode.PARAM_VALIDATE_ERROR);
}
}
}
@Component
public class UserConflictCheckExecutor implements IFlowExecutor {
@Autowired
private UserMapper userMapper;
@Override
public void execute(IFlowContext iFlowContext) {
RegisterFlowContext registerFlowContext = (RegisterFlowContext) iFlowContext;
if (StringUtils.isNotEmpty(registerFlowContext.getLoginId())) {
LambdaQueryWrapper<UserDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserDO::getLoginId, registerFlowContext.getLoginId());
Integer count = userMapper.selectCount(queryWrapper);
if (count > 0) {
throw new UicException(ErrorCode.USER_CONFLICT_ERROR);
}
}
LambdaQueryWrapper<UserDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserDO::getEmail, registerFlowContext.getEmail());
Integer count = userMapper.selectCount(queryWrapper);
if (count > 0) {
throw new UicException(ErrorCode.USER_CONFLICT_ERROR);
}
}
}
@Component
public class UserRoleRichExecutor implements IFlowExecutor {
@Override
public void execute(IFlowContext iFlowContext) {
RegisterFlowContext registerFlowContext = (RegisterFlowContext) iFlowContext;
UserRole userRole = new UserRole();
String isSeller = registerFlowContext.getExtend(UserConstant.IS_SELLER);
if (StringUtils.isNotEmpty(isSeller) && Boolean.TRUE.toString().equals(isSeller)) {
userRole.addRole(UserRoleConstant.SELLER_ROLE);
}
String isBuyer = registerFlowContext.getExtend(UserConstant.IS_BUYER);
if (StringUtils.isNotBlank(isBuyer) && Boolean.TRUE.toString().equals(isBuyer)) {
userRole.addRole(UserRoleConstant.BUYER_ROLE);
}
registerFlowContext.setRoles(userRole.getRoles());
}
}
创建注册流程类
public class RegisterFlow extends AbstractFlow {
}
最后,创建配置类,将这些执行器按照顺序添加到RegisterFlow注册流程中,从而实现流程执行器在流程中的编排
@Configuration
public class FlowConfiguration {
@DependsOn({"registerFormCheckExecutor", "userConflictCheckExecutor",
"encryptPasswordExecutor", "userRoleRichExecutor",
"createUserExecutor", "buildUserTokenExecutor"})
@Bean
public RegisterFlow registerFlow(@Qualifier("registerFormCheckExecutor")IFlowExecutor registerFormCheckExecutor,
@Qualifier("userConflictCheckExecutor")IFlowExecutor userConflictCheckExecutor,
@Qualifier("encryptPasswordExecutor")IFlowExecutor encryptPasswordExecutor,
@Qualifier("userRoleRichExecutor")IFlowExecutor userRoleRichExecutor,
@Qualifier("createUserExecutor")IFlowExecutor createUserExecutor,
@Qualifier("buildUserTokenExecutor")IFlowExecutor buildUserTokenExecutor) {
RegisterFlow registerFlow = new RegisterFlow();
registerFlow.addFlowExecutor(registerFormCheckExecutor);
registerFlow.addFlowExecutor(userConflictCheckExecutor);
registerFlow.addFlowExecutor(encryptPasswordExecutor);
registerFlow.addFlowExecutor(userRoleRichExecutor);
registerFlow.addFlowExecutor(createUserExecutor);
registerFlow.addFlowExecutor(buildUserTokenExecutor);
return registerFlow;
}
}
经过上述修改后,service层代码得到简化, 内容如下:
@Component
public class UserServiceImpl implements IUserService{
@Autowired
private UserMapper userMapper;
@Autowired
private RegisterFlow registerFlow;
@Override
public UserDO getById(Integer id) {
return userMapper.selectById(id);
}
@Override
public ResultT<String> register(RegisterRequest registerRequest) {
RegisterFlowContext registerFlowContext = new RegisterFlowContext();
registerFlowContext.setLoginId(registerRequest.getLoginId());
registerFlowContext.setEmail(registerRequest.getEmail());
registerFlowContext.setPassword(registerRequest.getPassword());
if (registerRequest.getExtendMaps() != null) {
registerRequest.getExtendMaps().forEach(registerFlowContext::putExtend);
}
registerFlow.execute(registerFlowContext);
return ResultT.success(registerFlowContext.getToken());
}
@Override
public boolean updateUser(UserDO userDO) {
return false;
}
}
缺点
上述方式虽然能将业务流程细分为不同的执行器,从而达到职责分离的作用,但是,当业务流程中,涉及分支判断,不同分支走不同业务逻辑时,上述实现方式较难支撑相关需求
流程引擎实现流程编排
对于市面上常用的几种流程引擎,都包含下列几种功能:
- 事件:开始事件、结束事件
- 活动activity:用户任务(User Task), 服务任务(Service Task) ,子流程(Sub Process)
- 网关GateWay:排他网关、并行网关、事件网关
在我们之前提到将业务流程抽象为执行类依次执行,这里的执行类其实就相当于流程引擎的服务任务(Service Task),而对于分支的判断,可以使用流程引擎的网关,此外,还可以通过用户任务,定位到当前节点,执行之前未完成、中断的流程。
实现
下面简单介绍注册流程如何通过流程引擎的服务任务编排实现。首先创建对应的流程文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<activiti id="register_flow">
<!--节点定义-->
<startEvent id="startEvent"/>
<serviceTask id="registerFormCheck" name="registerFormCheck" description="注册表单校验" class="com.yang.application.register.activiti.RegisterFormCheckActivity"/>
<serviceTask id="userConflictCheck" name="userConflictCheck" description="用户冲突定位" class="com.yang.application.register.activiti.UserConflictCheckActivity"/>
<serviceTask id="encryptPassword" name="encryptPassword" description="密码加密" class="com.yang.application.register.activiti.EncryptPasswordActivity"/>
<serviceTask id="userRoleRich" name="userRoleRich" description="用户权限填充" class="com.yang.application.register.activiti.UserRoleRichActivity"/>
<serviceTask id="createUser" name="createUser" description="创建用户" class="com.yang.application.register.activiti.CreateUserActivity"/>
<serviceTask id="buildUserToken" name="buildUserToken" description="创建用户token" class="com.yang.application.register.activiti.BuildUserTokenActivity"/>
<endEvent id="endEvent"/>
<!--节点执行顺序编排-->
<sequenceFlow source="startEvent" target="registerFormCheck"/>
<sequenceFlow source="registerFormCheck" target="userConflictCheck"/>
<sequenceFlow source="userConflictCheck" target="encryptPassword"/>
<sequenceFlow source="encryptPassword" target="userRoleRich"/>
<sequenceFlow source="userRoleRich" target="createUser"/>
<sequenceFlow source="createUser" target="buildUserToken"/>
<sequenceFlow source="buildUserToken" target="endEvent"/>
</activiti>
然后创建对应的服务任务:
@Component
public class RegisterFormCheckActivity implements IServiceTask {
@Override
public void doElse(ActivitiEngineRequest request, ActivitiEngineResponse response) {
RegisterRequest registerRequest = (RegisterRequest) request.getBaseRequest();
if (StringUtils.isEmpty(registerRequest.getEmail())
|| StringUtils.isEmpty(registerRequest.getPassword())) {
throw new UicException(ErrorCode.PARAM_VALIDATE_ERROR);
}
}
@Override
public Object buildDomainRequest(ActivitiEngineRequest request, ActivitiEngineResponse response) {
return null;
}
@Override
public Object apply(Object o) {
return null;
}
@Override
public void attachment(Object o, ActivitiEngineResponse response) {
}
}
@Component
public class UserConflictCheckActivity implements IServiceTask<UserQueryDomainRequest, UserQueryDomainResponse> {
@Autowired
private UserDomainService userDomainService;
@Override
public UserQueryDomainRequest buildDomainRequest(ActivitiEngineRequest request, ActivitiEngineResponse response) {
return null;
}
@Override
public UserQueryDomainResponse apply(UserQueryDomainRequest userQueryDomainRequest) {
return null;
}
@Override
public void doElse(ActivitiEngineRequest request, ActivitiEngineResponse response) {
RegisterRequest registerRequest = (RegisterRequest) request.getBaseRequest();
if (StringUtils.isNotEmpty(registerRequest.getLoginId())) {
UserQueryDomainRequest userQueryDomainRequest = new UserQueryDomainRequest.UserQueryDomainRequestBuilder()
.userQueryType(UserQueryType.LOGIN_ID)
.queryMessage(registerRequest.getLoginId())
.build();
UserQueryDomainResponse userQueryDomainResponse = userDomainService.query(userQueryDomainRequest);
if (!CollectionUtils.isEmpty(userQueryDomainResponse.getUserAccountList())) {
throw new UicException(ErrorCode.USER_CONFLICT_ERROR);
}
}
UserQueryDomainRequest userQueryDomainRequest = new UserQueryDomainRequest.UserQueryDomainRequestBuilder()
.userQueryType(UserQueryType.EMAIL)
.queryMessage(registerRequest.getEmail())
.build();
UserQueryDomainResponse userQueryDomainResponse = userDomainService.query(userQueryDomainRequest);
if (!CollectionUtils.isEmpty(userQueryDomainResponse.getUserAccountList())) {
throw new UicException(ErrorCode.USER_CONFLICT_ERROR);
}
}
@Override
public void attachment(UserQueryDomainResponse userQueryDomainResponse, ActivitiEngineResponse response) {
}
}
@Component
public class EncryptPasswordActivity implements IServiceTask<UserPasswordEncryptDomainRequest, UserPasswordEncryptDomainResponse> {
@Autowired
private UserPasswordDomainService userPasswordDomainService;
@Override
public UserPasswordEncryptDomainRequest buildDomainRequest(ActivitiEngineRequest request, ActivitiEngineResponse response) {
RegisterRequest registerRequest = (RegisterRequest) request.getBaseRequest();
UserPasswordEncryptDomainRequest userPasswordEncryptDomainRequest = new UserPasswordEncryptDomainRequest();
String encryptType = null;
if (registerRequest.getExtendMaps() != null) {
registerRequest.getExtendMaps().get("encryptType");
}
EncryptTypeEnum encryptTypeEnum = EncryptTypeEnum.parseByType(encryptType);
userPasswordEncryptDomainRequest.setEncryptType(encryptTypeEnum);
userPasswordEncryptDomainRequest.setPlainPassword(registerRequest.getPassword());
return userPasswordEncryptDomainRequest;
}
@Override
public UserPasswordEncryptDomainResponse apply(UserPasswordEncryptDomainRequest userPasswordEncryptDomainRequest) {
return userPasswordDomainService.encryptPassword(userPasswordEncryptDomainRequest);
}
@Override
public void attachment(UserPasswordEncryptDomainResponse userPasswordEncryptDomainResponse, ActivitiEngineResponse response) {
UserModel userModel = (UserModel) response.getResponse();
if (userModel == null) {
userModel = new UserModel();
response.setResponse(userModel);
}
userModel.setEncryptPassword(userPasswordEncryptDomainResponse.getEncryptPassword());
}
}
@Component
public class UserRoleRichActivity implements IServiceTask<UserRoleApplyDomainRequest, UserRoleApplyDomainResponse> {
@Autowired
private UserRoleDomainService userRoleDomainService;
@Override
public UserRoleApplyDomainRequest buildDomainRequest(ActivitiEngineRequest request, ActivitiEngineResponse response) {
RegisterRequest registerRequest = (RegisterRequest) request.getBaseRequest();
UserRoleApplyDomainRequest userRoleApplyDomainRequest = new UserRoleApplyDomainRequest();
if (registerRequest.getExtendMaps() != null) {
userRoleApplyDomainRequest.setFeatureMap(registerRequest.getExtendMaps());
} else {
userRoleApplyDomainRequest.setFeatureMap(new HashMap<>());
}
return userRoleApplyDomainRequest;
}
@Override
public UserRoleApplyDomainResponse apply(UserRoleApplyDomainRequest userRoleApplyDomainRequest) {
return userRoleDomainService.applyUserRole(userRoleApplyDomainRequest);
}
@Override
public void attachment(UserRoleApplyDomainResponse userRoleApplyDomainResponse, ActivitiEngineResponse response) {
UserModel userModel = (UserModel) response.getResponse();
userModel.setUserRole(userRoleApplyDomainResponse.getUserRole());
}
}
@Component
public class CreateUserActivity implements IServiceTask<UserCreateDomainRequest, UserCreateDomainResponse> {
@Autowired
private UserDomainService userDomainService;
@Override
public UserCreateDomainRequest buildDomainRequest(ActivitiEngineRequest request, ActivitiEngineResponse response) {
RegisterRequest registerRequest = (RegisterRequest) request.getBaseRequest();
UserModel userModel = (UserModel) response.getResponse();
UserCreateDomainRequest userCreateDomainRequest = new UserCreateDomainRequest();
userCreateDomainRequest.setLoginId(registerRequest.getLoginId());
userCreateDomainRequest.setEmail(registerRequest.getEmail());
Map<String, String> featureMap = new HashMap<>();
if (userModel.getUserRole() != null) {
userCreateDomainRequest.setRoles(userModel.getUserRole().getRoles());
}
if (userModel.getEncryptPassword() != null) {
userCreateDomainRequest.setPlainPassword(userModel.getEncryptPassword().getPlainPassword());
userCreateDomainRequest.setPassword(userModel.getEncryptPassword().getEncryptPassword());
featureMap.put("encryptType", userModel.getEncryptPassword().getEncryptType().getType());
}
userCreateDomainRequest.setFeatureMap(featureMap);
UserAccount userAccount = convert2UserAccount(userCreateDomainRequest);
userModel.setUserAccount(userAccount);
return userCreateDomainRequest;
}
private UserAccount convert2UserAccount(UserCreateDomainRequest userCreateDomainRequest) {
UserAccount userAccount = new UserAccount();
userAccount.setLoginId(userCreateDomainRequest.getLoginId());
userAccount.setEmail(userCreateDomainRequest.getEmail());
userAccount.setFeatureMap(userCreateDomainRequest.getFeatureMap());
return userAccount;
}
@Override
public UserCreateDomainResponse apply(UserCreateDomainRequest userCreateDomainRequest) {
if (StringUtils.isEmpty(userCreateDomainRequest.getLoginId())) {
userCreateDomainRequest.setLoginId(UUID.randomUUID().toString().replaceAll("-", ""));
}
return userDomainService.createUser(userCreateDomainRequest);
}
@Override
public void attachment(UserCreateDomainResponse userCreateDomainResponse, ActivitiEngineResponse response) {
if (userCreateDomainResponse.isSuccess()) {
UserModel userModel = (UserModel) response.getResponse();
userModel.getUserAccount().setId(userCreateDomainResponse.getUserId());
return;
}
throw new UicException(ErrorCode.PERSISTENCE_DATA_ERROR);
}
}
@Component
public class BuildUserTokenActivity implements IServiceTask<ApplyTokenDomainRequest, TokenDomainResponse> {
@Autowired
private UserTokenDomainService userTokenDomainService;
@Override
public ApplyTokenDomainRequest buildDomainRequest(ActivitiEngineRequest request, ActivitiEngineResponse response) {
UserModel userModel = (UserModel) response.getResponse();
ApplyTokenDomainRequest applyTokenDomainRequest = new ApplyTokenDomainRequest();
applyTokenDomainRequest.setUserId(userModel.getId());
UserAccount userAccount = userModel.getUserAccount();
Map<String, String> attachments = new HashMap<>();
attachments.put("email", userAccount.getEmail());
attachments.put("loginId", userAccount.getLoginId());
if (userModel.getUserRole() != null) {
attachments.put("roles", userModel.getUserRole().getRoles());
}
applyTokenDomainRequest.setAttachments(attachments);
return applyTokenDomainRequest;
}
@Override
public TokenDomainResponse apply(ApplyTokenDomainRequest applyTokenDomainRequest) {
return userTokenDomainService.applyToken(applyTokenDomainRequest);
}
@Override
public void attachment(TokenDomainResponse tokenDomainResponse, ActivitiEngineResponse response) {
UserTokenModel userToken = tokenDomainResponse.getUserToken();
UserModel userModel = (UserModel) response.getResponse();
userModel.setUserToken(userToken);
}
}
然后我们修改service类,加上执行流程引擎的注册方法:
@Override
public ResultT<String> register2(RegisterRequest registerRequest) {
ActivitiEngineRequest<RegisterRequest> activitiEngineRequest = new ActivitiEngineRequest<>();
activitiEngineRequest.setBaseRequest(registerRequest);
ActivitiEngineResponse<UserModel> activitiEngineResponse = ActivitiFlowManager.startEngine("register_flow.xml", activitiEngineRequest);
UserModel userModel = activitiEngineResponse.getResponse();
if (userModel != null && userModel.getUserToken() != null) {
String token = userModel.getUserToken().getToken();
return ResultT.success(token);
}
return ResultT.fail();
}
添加测试方法:
@Test
public void testEngineRegister() {
RegisterRequest registerRequest = new RegisterRequest();
registerRequest.setLoginId("test2");
registerRequest.setEmail("[email protected]");
registerRequest.setPassword("hello1234");
ResultT<String> resultT = userService.register2(registerRequest);
System.out.println(resultT);
System.out.println(resultT.getData());
}
执行结果如下:
缺点
- 学习成本高:流程引擎涉及的概念较多,包括流程设计、执行、监控和优化等,此外流程引擎对程序员业务逻辑的理解能力要求较高,如何对业务流程进行拆分?拆分的粒度是多少?都是值得考量的问题。
- 使用成本高:大多数流程引擎需要引入数据库来记录流程执行上下文,导致使用成本、维护成本增加。