Service层瘦身思考

news/2024/10/3 22:23:46 标签: java

背景

传统的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("2827523201@qq.com");
        registerRequest.setPassword("hello1234");
        ResultT<String> resultT = userService.register2(registerRequest);
        System.out.println(resultT);
        System.out.println(resultT.getData());
    }

执行结果如下:

缺点
  • 学习成本高:流程引擎涉及的概念较多,包括流程设计、执行、监控和优化等,此外流程引擎对程序员业务逻辑的理解能力要求较高,如何对业务流程进行拆分?拆分的粒度是多少?都是值得考量的问题。
  • 使用成本高:大多数流程引擎需要引入数据库来记录流程执行上下文,导致使用成本、维护成本增加。

http://www.niftyadmin.cn/n/5689044.html

相关文章

k8s-pod的管理及优化设置

Pod是Kubernetes&#xff08;k8s&#xff09;中最小的资源管理组件&#xff0c;也是最小化运行容器化应用的资源对象。以下是对Pod的详细介绍&#xff1a; 一、Pod的基本概念 定义&#xff1a;Pod是Kubernetes中可以创建和管理的最小单元&#xff0c;是资源对象模型中由用户创…

滚雪球学Oracle[2.5讲]:数据库初始化配置

全文目录&#xff1a; 前言一、配置文件的高级参数设置1.1 open_cursors&#xff1a;游标打开数量限制案例演示 1.2 session_cached_cursors&#xff1a;会话缓存游标数量案例演示 1.3 pga_aggregate_target与sga_target&#xff1a;内存分配优化案例演示 二、内存管理模式的选…

每日一练:杨辉三角

118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 题目要求&#xff1a; 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,…

Qt 中的 QChartView

深入理解 Qt 的 QChartView&#xff1a;图表展示与交互 QChartView 是 Qt Charts 模块中的一个核心类&#xff0c;它用于在 Qt 应用程序中显示图表&#xff0c;并支持多种用户交互方式。它继承自 QGraphicsView&#xff0c;通过封装 QChart&#xff0c;为用户提供了强大的图表…

【Linux】进程管理:状态与优先级调度的深度分析

✨ 山海自有归期&#xff0c;风雨自有相逢 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;Linux—登神长阶 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1…

如何使用工具删除 iPhone 上的图片背景

在 iPhone 上删除背景图像变得简单易行。感谢最近 iOS 更新中引入的新功能。如今&#xff0c;iOS 用户现在可以毫不费力地删除背景&#xff0c;而无需复杂的应用程序。在这篇文章中&#xff0c;您将学习如何使用各种方法去除 iPhone 上的背景。这可确保您可以选择最适合您偏好的…

【漏洞复现】灵当CRM multipleUpload.php接口处存在文件上传漏洞

》》》产品描述《《《 灵当CRM致力于为企业提供客户管理数字化、销售管理自动化、服务管理智能化、项目管理一体化的个性化CRM行业解决方案,构建全生命周期的数字化管理体系,实现可持续的业绩增长! 》》》漏洞描述《《《 灵当CRM系统接口multipleUpload.php文件上传漏洞&#x…

04-SpringBootWeb案例(下)

3. 员工管理 完成了部门管理的功能开发之后&#xff0c;我们进入到下一环节员工管理功能的开发。 基于以上原型&#xff0c;我们可以把员工管理功能分为&#xff1a; 分页查询&#xff08;今天完成&#xff09;带条件的分页查询&#xff08;今天完成&#xff09;删除员工&am…