ddd-重构项目


DDD领域驱动设计之代码重构

以用户功能为例

1. 重构前代码片段

  • UserController.java

/**
 * 

* 前端控制器 *

* * @author xujie * @since 2021-06-03 */ @RestController @RequestMapping("/user") @Api(value = "用户", tags = "用户") public class UserController { @Autowired private UserService userService; @ApiOperation(value = "统计用户有多少朋友", notes = "统计用户有多少朋友") @GetMapping("/friend/count") public KpResult getUserHaveFriendNumber(@Valid @Size(max = 64, min = 16) String userUniqueId) { KpResult integerKpResult = new KpResult<>(userService.countUserHaveFriendNumber(userUniqueId)); integerKpResult.setTraceId(MDC.get(TraceConstant.TRACE_KEY)); return integerKpResult; } @ApiOperation(value = "获取当前用户个人信息", notes = "获取当前用户个人信息") @GetMapping("/current/query") public KpResult getCurrentUser() { String currentUserUniqueId = CurrentUserUtil.getCurrentUserUniqueId(); Optional.ofNullable(currentUserUniqueId).orElseThrow(() -> new CommonAssertException(ApplicationCodes.CUREENT_USER_NOT_EXIST)); KpResult userDTOKpResult = new KpResult<>(userService.selectCurrentUser(currentUserUniqueId)); userDTOKpResult.setTraceId(MDC.get(TraceConstant.TRACE_KEY)); return userDTOKpResult; } @ApiOperation(value = "登陆", notes = "登陆") @PostMapping(value = "/login") public KpResult login(@RequestBody @Valid LoginUserParam loginUserParam) { KpResult tokenDTOKpResult = new KpResult<>(userService.login(loginUserParam)); tokenDTOKpResult.setTraceId(MDC.get(TraceConstant.TRACE_KEY)); return tokenDTOKpResult; } @ApiOperation(value = "注册", notes = "注册") @PostMapping(value = "/register") public KpResult register(@RequestBody @Valid RegisterUserParam registerUserParam) { KpResult tokenDTOKpResult = new KpResult<>(userService.register(registerUserParam)); tokenDTOKpResult.setTraceId(MDC.get(TraceConstant.TRACE_KEY)); return tokenDTOKpResult; } @ApiOperation(value = "搜索用户", notes = "搜索用户") @PostMapping(value = "/search") public KpResult>> search(@RequestBody @Valid SearchUserParam searchUserParam) { KpResult>> result = new KpResult>>(); result.setData(userService.queryUser(searchUserParam)); result.setTraceId(MDC.get(TraceConstant.TRACE_KEY)); return result; } @ApiOperation(value = "更新用户", notes = "更新用户") @PostMapping(value = "/profile/update") public KpResult updateUser(@RequestBody @Valid UpdateUserParam updateUserParam) { KpResult result = new KpResult(userService.updateCurrentUser(updateUserParam)); result.setTraceId(MDC.get(TraceConstant.TRACE_KEY)); return result; } @ApiOperation(value = "当前用户朋友", notes = "当前用户朋友") @PostMapping(value = "/my/friend") public KpResult>> query(@RequestBody @Valid Pageable pageable) { String currentUserUniqueId = CurrentUserUtil.getCurrentUserUniqueId(); Optional.ofNullable(currentUserUniqueId).orElseThrow(() -> new CommonAssertException(ApplicationCodes.CUREENT_USER_NOT_EXIST)); KpResult>> result = new KpResult>>(userService.queryMyFriend(pageable, currentUserUniqueId)); result.setTraceId(MDC.get(TraceConstant.TRACE_KEY)); return result; } @ApiOperation(value = "朋友邀请码", notes = "朋友邀请码") @PostMapping(value = "/my/friend/code/get") public KpResult getInvite() { String currentUserUniqueId = CurrentUserUtil.getCurrentUserUniqueId(); Optional.ofNullable(currentUserUniqueId).orElseThrow(() -> new CommonAssertException(ApplicationCodes.CUREENT_USER_NOT_EXIST)); KpResult result = new KpResult(userService.createInvite(currentUserUniqueId)); result.setTraceId(MDC.get(TraceConstant.TRACE_KEY)); return result; } @ApiOperation(value = "登录验证码", notes = "登录验证码") @GetMapping(value = "/login/verification/code/get") public KpResult getVerificationCodeByPhone(@Valid @Size(max = 11, min = 11) @NotEmpty String phone) { Optional.ofNullable(phone).orElseThrow(() -> new CommonAssertException(ApplicationCodes.CUREENT_USER_NOT_EXIST)); KpResult result = new KpResult(userService.getVerificationCodeByPhone(phone)); result.setTraceId(MDC.get(TraceConstant.TRACE_KEY)); return result; } }
  • UserServiceImpl.java
/**
 * 

* 服务实现类 *

* * @author xujie * @since 2021-06-03 */ @Slf4j @Service public class UserServiceImpl extends ServiceImpl implements UserService { @Autowired private UserHelper userHelper; @Autowired private FriendService friendService; @Autowired private IIdGenerator iIdGenerator; @Autowired private BsProvinceHelper bsProvinceHelper; @Autowired private BsAreaHelper bsAreaHelper; @Autowired private AreaUtil areaUtil; @Autowired private UserConfigService userConfigService; @Autowired private RedisUtil redisUtil; @Autowired private AliOssUtil ossUtil; @Autowired private AliSmsUtil smsUtil; @RedisCache(key = "user.by.user.id", fieldKey = "#userUniqueId") @Override public Integer countUserHaveFriendNumber(String userUniqueId) { Optional.ofNullable(userUniqueId).orElseThrow(() -> new CommonAssertException(CommonConstant.REQUEST_PARAM_ERROR)); TUser user = userHelper.selectByUserUniqueId(userUniqueId); Optional.ofNullable(user).orElseThrow(() -> new CommonAssertException(ApplicationCodes.USER_NOT_EXIST)); return friendService.selectCountUserHaveFriendNumber(userUniqueId); } @RedisCache(key = "user.by.current.user.id", fieldKey = "#currentUserUniqueId") @Override public UserDTO selectCurrentUser(String currentUserUniqueId) { UserDTO userDTO = new UserDTO(); TUser user = userHelper.selectByUserUniqueId(currentUserUniqueId); Optional.ofNullable(user).orElseThrow(() -> new CommonAssertException(ApplicationCodes.USER_NOT_EXIST)); //个人隐私设置 UserConfig dbUserConfig = userConfigService.selectByUserUniqueId(currentUserUniqueId); UserConfigDTO userConfig = new UserConfigDTO(); userConfig.setUserUniqueId(dbUserConfig.getUserUniqueId()); userConfig.setUserConfigUniqueId(dbUserConfig.getUserConfigUniqueId()); userConfig.setVisbleBase(dbUserConfig.getIsVisibleAge()); userConfig.setVisbleName(dbUserConfig.getIsVisibleName()); userConfig.setVisblePhone(dbUserConfig.getIsVisiblePhone()); userConfig.setVisbleQq(dbUserConfig.getIsVisibleQq()); userConfig.setVisbleWeixin(dbUserConfig.getIsVisibleWeixin()); userDTO.setUserConfigDTO(userConfig); BeanUtils.copyProperties(user, userDTO, "password"); userDTO.setAvatar(ossUtil.getUrl(ossUtil.getAvatarBucketName(), currentUserUniqueId, CommonConstant.AVATAR_TTL)); userDTO.setBirthday(user.getBirthday()); if (Objects.nonNull(user.getApprovalTime())) { userDTO.setApprovalTime(String.format("%d年%d月%d日", user.getApprovalTime().getYear(), user.getApprovalTime().getMonth().getValue(), user.getApprovalTime().getDayOfMonth())); } // 统计 StatisticsDTO statisticsDTO = new StatisticsDTO(); //统计多少朋友 Integer total = friendService.selectCountUserHaveFriendNumber(currentUserUniqueId); statisticsDTO.setCountFriend(total); //获取朋友分布 List friends = friendService.selectByUserUniqueId(currentUserUniqueId); statisticsDTO.setFriendInArea(getFriendsInArea(friends)); //月结识率 Integer countInMonth = friendService.selectCountFriendInDayByUserUniqueId(currentUserUniqueId, 30); if (total != 0) { DecimalFormat decimalFormat = new DecimalFormat("0.00"); decimalFormat.format((float) countInMonth / total); BigDecimal countInMonthBigDecimal = new BigDecimal(countInMonth); BigDecimal totalBigDecimal = new BigDecimal(total); BigDecimal divide = countInMonthBigDecimal.divide(totalBigDecimal, BigDecimal.ROUND_HALF_UP); BigDecimal hundred = new BigDecimal(100); statisticsDTO.setMakeFriendsInMonthRate(String.format("%s%%", divide.multiply(hundred))); } userDTO.setStatisticsDTO(statisticsDTO); return userDTO; } private List getFriendsInArea(List friends) { if (!CollectionUtils.isEmpty(friends)) { Set friendUserUniqueIds = friends.stream(). map(Friend::getFriendUniqueId).collect(Collectors.toSet()); List userFriends = userHelper.selectByUserUniqueIds(friendUserUniqueIds); if (CollectionUtils.isEmpty(userFriends)) { throw new CommonAssertException(ApplicationCodes.USER_FRIEND_NOT_EXIST); } List userFriendCurrentHomeList = userFriends.stream() .map(TUser::getCurrentHome).collect(Collectors.toList()); // 去重 Set provinceAndAreaCodes = Sets.newHashSet(); if (!CollectionUtils.isEmpty(userFriendCurrentHomeList)) { userFriendCurrentHomeList.stream().forEach(userFriendCurrentHome -> { if (StringUtils.isNotEmpty(userFriendCurrentHome)) { String[] area = userFriendCurrentHome.split(AREA_SPLIT); // format : province_code,city_code,area_code,street_code provinceAndAreaCodes.add(area[0] + AREA_SPLIT + area[2]); } }); Set provinceCodes = Sets.newHashSet(); Set areaCodes = Sets.newHashSet(); if (!CollectionUtils.isEmpty(provinceAndAreaCodes)) { provinceAndAreaCodes.stream().forEach(provinceAndAreaCode -> { String[] provinceAndAreaCodeArr = provinceAndAreaCode.split(AREA_SPLIT); // format : province_code,area_code provinceCodes.add(provinceAndAreaCodeArr[0]); areaCodes.add(provinceAndAreaCodeArr[1]); }); } List bsProvinces = Lists.newArrayList(); if (!CollectionUtils.isEmpty(provinceCodes)) { bsProvinces.addAll(bsProvinceHelper.selectByProvinceCodes(provinceCodes)); } List bsAreas = Lists.newArrayList(); if (!CollectionUtils.isEmpty(areaCodes)) { bsAreas.addAll(bsAreaHelper.selectByAreaCodes(areaCodes)); } if (!CollectionUtils.isEmpty(provinceCodes) && !CollectionUtils.isEmpty(areaCodes) && provinceCodes.size() != areaCodes.size()) { throw new CommonAssertException(ApplicationCodes.USER_CURRENT_HOME); } List formatAreaList = Lists.newArrayList(); //拼装 format : {province_name,area_name} provinceAndAreaCodes.stream().forEach(provinceAndAreaCode -> { String formatArea = ""; for (int i = 0; i < bsProvinces.size(); i++) { formatArea = bsProvinces.get(i).getShortName() + "," + bsAreas.get(i).getShortName(); formatAreaList.add(String.format("{%s}", formatArea)); } formatAreaList.add(String.format("{%s}", formatArea)); }); return formatAreaList; } } return Collections.EMPTY_LIST; } @Override public TokenDTO login(LoginUserParam loginUserParam) { TUser userByPhone = userHelper.findUserByPhone(loginUserParam.getUserName()); Optional.ofNullable(userByPhone).orElseThrow(() -> new CommonAssertException(ApplicationCodes.USER_NOT_EXIST)); //审核通过才放行 if (!Objects.equals(userByPhone.getApprovalStatus(), UserApprovalStatusEnum.PASSED.getCode())) { return new TokenDTO(); } // TODO 待上线 去掉注解即可 验证码通过放行 String defaultKey = CommonConstant.GET_LOGIN_VERIFICATION_CODE_KEY + StringUtils.trim(loginUserParam.getUserName()); Object code = redisUtil.get(defaultKey); if (Objects.isNull(code)) { throw new CommonAssertException(ApplicationCodes.VERIFICATION_CODE_NOT_EXIST); } if (!Objects.equals(code.toString(), StringUtils.trim(loginUserParam.getValidateCode()))) { throw new CommonAssertException(ApplicationCodes.VERIFICATION_CODE_IS_ERROR); } if (Objects.equals(userByPhone.getPassword(), Md5Util.getMD5(StringUtils.trim(loginUserParam.getPassword())))) { String jwt = CurrentUserUtil.createJWT(userByPhone.getUserUniqueId(), userByPhone.getUserUniqueId(), CommonConstant.JWT_TTL); TokenDTO tokenDTO = new TokenDTO(); tokenDTO.setToken(jwt); tokenDTO.setLevel(userByPhone.getApprovalLevel()); tokenDTO.setUserUniqueId(userByPhone.getUserUniqueId()); tokenDTO.setNickName(userByPhone.getNickName()); redisUtil.delete(defaultKey); return tokenDTO; } else { throw new CommonAssertException(ApplicationCodes.USER_PASSWORD_ERROR); } } @Override @Transactional(rollbackFor = Exception.class) public boolean register(RegisterUserParam userParam) { Optional.ofNullable(userParam).orElseThrow(() -> new CommonAssertException(CommonConstant.REQUEST_PARAM_ERROR)); TUser register = new TUser(); register.setNickName(SampleRandomUtil.getRandomString(5)); register.setPassword(Md5Util.getMD5(StringUtils.trim(userParam.getPassword()))); register.setPhone(StringUtils.trim(userParam.getUserName())); register.setUserUniqueId(iIdGenerator.getHexId()); register.setApprovalTime(LocalDateTime.now()); boolean validateInvite = validateInvite(userParam.getInviteCode()); if (!validateInvite) { throw new CommonAssertException(ApplicationCodes.USER_INVITE_ERROR); } // 存的是邀请人的 userUniqueId String inviteCodeValue = getInviteCodeValueToUserUniqueId(userParam.getInviteCode()); register.setInviteBy(inviteCodeValue); register.setApprovalStatus(UserApprovalStatusEnum.PASSED.getCode()); UserConfig userConfig = getUserRegisterDefaultConfig(register); if (userHelper.insert(register) && userConfigService.insert(userConfig)) { Friend friend = new Friend(); friend.setApprovalStatus(FriendApprovalStatusEnum.PASSED.getCode()); friend.setUserUniqueId(inviteCodeValue); friend.setFriendUniqueId(register.getUserUniqueId()); friendService.insert(friend); Friend self = new Friend(); self.setApprovalStatus(FriendApprovalStatusEnum.PASSED.getCode()); self.setUserUniqueId(register.getUserUniqueId()); self.setFriendUniqueId(inviteCodeValue); friendService.insert(self); // 清除redis key redisUtil.delete(CommonConstant.INVITE_CODE + userParam.getInviteCode()); redisUtil.delete(CommonConstant.USER_INVITE_CODE_KEY + inviteCodeValue); return true; } return false; } private UserConfig getUserRegisterDefaultConfig(TUser user) { UserConfig userConfig = new UserConfig(); userConfig.setIsIncludedSearchAge(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchBirthday(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchCurrentHome(YesNoEnum.NO.getCode()); userConfig.setIsVisibleCurrentDynamic(YesNoEnum.YES.getCode()); userConfig.setIsVisibleCurrentHome(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchDouyin(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchFeelingStatus(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchKuaishou(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchMe(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchNickName(YesNoEnum.YES.getCode()); userConfig.setIsVisibleAge(YesNoEnum.NO.getCode()); userConfig.setIsVisibleWeixin(YesNoEnum.NO.getCode()); userConfig.setIsVisiblePhone(YesNoEnum.NO.getCode()); userConfig.setIsVisibleName(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchOriginalFamilyHome(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchPhone(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchQq(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchSex(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchWeixin(YesNoEnum.NO.getCode()); userConfig.setIsVisibleCurrentDynamic(YesNoEnum.NO.getCode()); userConfig.setIsVisibleGoodCounter(YesNoEnum.NO.getCode()); userConfig.setUserUniqueId(user.getUserUniqueId()); userConfig.setUserConfigUniqueId(iIdGenerator.getIdStr()); userConfig.setIsVisibleWork(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchWork(YesNoEnum.NO.getCode()); userConfig.setIsVisibleIdCard(YesNoEnum.NO.getCode()); userConfig.setIsIncludedSearchIdCard(YesNoEnum.NO.getCode()); return userConfig; } @Override public PageDTO> queryUser(SearchUserParam searchUserParam) { String currentUserUniqueId = CurrentUserUtil.getCurrentUserUniqueId(); Optional.ofNullable(currentUserUniqueId).orElseThrow(() -> new CommonAssertException(ApplicationCodes.CUREENT_USER_NOT_EXIST)); // 如果要查朋友的朋友 商品名称 会多出来几个 left join 影响性能 // searchUserParam.getGoodName() TUser current = userHelper.selectByUserUniqueId(currentUserUniqueId); Optional.ofNullable(current).orElseThrow(() -> new CommonAssertException(ApplicationCodes.CUREENT_USER_NOT_EXIST)); Page page = userHelper.selectByCondition(searchUserParam.getPageNo(), searchUserParam.getPageSize(), searchUserParam.getSearchWord(), currentUserUniqueId); List userDTOList = Lists.newArrayList(); List records = page.getRecords(); if (!CollectionUtils.isEmpty(records)) { Set userUniqueIds = records.stream().map(TUser::getUserUniqueId).collect(Collectors.toSet()); // NOTE ids -> select single redis, 避免搜索组合过多导致redis宕机 List userConfigDTOS = Lists.newArrayList(); userUniqueIds.stream().forEach(userUniqueId -> { UserConfig userConfig = userConfigService.selectByUserUniqueId(userUniqueId); UserConfigDTO userConfigDTO = new UserConfigDTO(); UserConfigDTO newUserConfigDTO = UserConvert.daoToConfigDTO(userConfigDTO, userConfig); userConfigDTOS.add(newUserConfigDTO); }); Optional.ofNullable(userConfigDTOS).orElseThrow(() -> new CommonAssertException(ApplicationCodes.USER_CONFIG_NOT_EXIST)); // 处理用户设置的安全隐私问题 if (CollectionUtils.isEmpty(userConfigDTOS)) { throw new CommonAssertException(ApplicationCodes.USER_SAFE_CONFIG_NOT_EXIST); } Map userConfigMap = userConfigDTOS.stream().collect(Collectors.toMap(it -> it.getUserUniqueId(), it -> it)); // 处理朋友关系 // NOTE ids -> select single redis, 避免搜索组合过多导致redis宕机 List friendList = Lists.newArrayList(); userUniqueIds.stream().forEach(userUniqueId -> { friendList.addAll(friendService.selectByUserUniqueId(userUniqueId)); }); Map searchMappingToMapper = Maps.newHashMap(); Map> searchFriendMapper = Maps.newHashMap(); if (!CollectionUtils.isEmpty(friendList)) { Map> searchFriendMap = friendList.stream() .collect(Collectors.groupingBy(Friend::getUserUniqueId)); searchFriendMapper.putAll(searchFriendMap); List users = userHelper.selectByUserUniqueIds(friendList.stream().map(Friend::getFriendUniqueId).collect(Collectors.toSet())); Optional.ofNullable(users).orElseThrow(() -> new CommonAssertException(ApplicationCodes.USER_NOT_EXIST)); searchMappingToMapper.putAll(users.stream().collect(Collectors.toMap(it -> it.getUserUniqueId(), it -> it))); } // 我的朋友 List myFriends = friendService.selectByUserUniqueId(currentUserUniqueId); List myFriendsUniqueIds = Lists.newArrayList(); if (!CollectionUtils.isEmpty(myFriends)) { myFriendsUniqueIds.addAll(myFriends.stream().map(Friend::getFriendUniqueId).collect(Collectors.toSet())); } records.stream().forEach(user -> { UserConfigDTO userConfig = userConfigMap.get(user.getUserUniqueId()); List searchFriendList = searchFriendMapper.get(user.getUserUniqueId()); UserDTO userDTO = new UserDTO(); userDTO.setUserUniqueId(user.getUserUniqueId()); userDTO.setAvatar(ossUtil.getUrl(ossUtil.getAvatarBucketName(), user.getUserUniqueId(), CommonConstant.AVATAR_TTL)); userDTO.setName(getDisplayText(Objects.equals(userConfig.getVisbleName(), YesNoEnum.YES.getCode()), user.getName())); userDTO.setAge(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()) ? user.getAge() : null); userDTO.setSex(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()) ? user.getSex() : null); userDTO.setFeelingStatus(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()) ? user.getFeelingStatus() : null); String displayBirthdayText = getDisplayText(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()), user.getBirthday()); userDTO.setBirthday(displayBirthdayText); userDTO.setCurrentDynamic(getDisplayText(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()), user.getCurrentDynamic())); String currentHome = areaUtil.getFormartDisplayArea(user.getCurrentHome()); if (StringUtils.isNotEmpty(currentHome) && currentHome.split(AREA_SPLIT).length == 4) { String[] split = currentHome.split(AREA_SPLIT); currentHome = split[0] + "," + split[2]; } String forMartFamilyHome = ""; if (StringUtils.isNotEmpty(user.getOriginalFamilyHome())) { forMartFamilyHome = areaUtil.getFormartDisplayArea(user.getOriginalFamilyHome()); if (StringUtils.isNotEmpty(forMartFamilyHome) && forMartFamilyHome.split(AREA_SPLIT).length == 4) { String[] split = forMartFamilyHome.split(AREA_SPLIT); forMartFamilyHome = split[0] + "," + split[2]; } } userDTO.setNickName(getDisplayText(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()), user.getNickName())); userDTO.setWeixin(getDisplayText(Objects.equals(userConfig.getVisbleWeixin(), YesNoEnum.YES.getCode()), user.getWeixin())); userDTO.setQq(getDisplayText(Objects.equals(userConfig.getVisbleQq(), YesNoEnum.YES.getCode()), user.getQq())); userDTO.setPhone(getDisplayText(Objects.equals(userConfig.getVisblePhone(), YesNoEnum.YES.getCode()), user.getPhone())); userDTO.setApprovalLevel(user.getApprovalLevel()); // 搜索的人中有我朋友的朋友 if (!CollectionUtils.isEmpty(searchFriendList) && !CollectionUtils.isEmpty(myFriends)) { Set includeFriends = searchFriendList.stream() .filter(searchFriend -> myFriendsUniqueIds.contains(searchFriend.getFriendUniqueId())) .collect(Collectors.toSet()); List includeFriendMappingToUserList = Lists.newArrayList(); includeFriends.stream().forEach(includeFriend -> { includeFriendMappingToUserList.add(searchMappingToMapper.get(includeFriend.getUserUniqueId())); }); userDTO.setIncludeMyFriendStr(includeFriendMappingToUserList.stream().map(TUser::getNickName).collect(Collectors.joining(","))); } userDTO.setProfile(String.format("%s\n", userDTO.toString())); userDTOList.add(userDTO); }); } PageDTO> pageDTO = new PageDTO<>(); pageDTO.setPageNo((int) page.getCurrent()); pageDTO.setPageSize((int) page.getSize()); pageDTO.setTotal((int) page.getTotal()); pageDTO.setData(userDTOList); pageDTO.isHasMore(pageDTO.getTotal(), pageDTO.getPageNo(), pageDTO.getPageSize()); return pageDTO; } @RedisEvictByKeysOnPrefix(prefix = "user", fieldKey = "#updateUserParam.userUniqueId") @Override @Transactional(rollbackFor = Exception.class) public boolean updateCurrentUser(UpdateUserParam updateUserParam) { if (Objects.isNull(updateUserParam)) { throw new CommonAssertException(ApplicationCodes.UPDATE_CURRENT_USER_PARAM_NOT_EXIST); } String userUniqueId = updateUserParam.getUserUniqueId(); if (!Objects.equals(CurrentUserUtil.getCurrentUserUniqueId(), userUniqueId)) { throw new CommonAssertException(ApplicationCodes.UPDATE_CURRENT_USER_NO_AUTH); } TUser dbUser = userHelper.selectByUserUniqueId(userUniqueId); if (Objects.isNull(dbUser)) { throw new CommonAssertException(ApplicationCodes.USER_NOT_EXIST); } boolean updateUser = userHelper.updateUser(UserConvert.paramToDAO(dbUser, updateUserParam)); if (updateUser) { UserConfig dbUserConfig = userConfigService.selectByUserUniqueId(userUniqueId); if (Objects.isNull(dbUserConfig)) { throw new CommonAssertException(ApplicationCodes.USER_CONFIG_NOT_EXIST); } UserConfig update = UserConvert.paramToConfigDAO(dbUserConfig, updateUserParam); return userConfigService.updateUserConfig(update); } return false; } @Override public PageDTO> queryMyFriend(Pageable pageable, String currentUserUniqueId) { Optional.ofNullable(currentUserUniqueId).orElseThrow(() -> new CommonAssertException(ApplicationCodes.USER_NOT_EXIST)); Page friendPage = friendService.selectByUserUniqueIdPageable(pageable, currentUserUniqueId); if (!CollectionUtils.isEmpty(friendPage.getRecords())) { Set myFriendsUniqueIds = friendPage.getRecords().stream().map(Friend::getFriendUniqueId).collect(Collectors.toSet()); List myFriendUsers = userHelper.selectByUserUniqueIds(myFriendsUniqueIds); Optional.ofNullable(myFriendUsers).orElseThrow(() -> new CommonAssertException(ApplicationCodes.USER_NOT_EXIST)); List userConfigDTOS = userConfigService.selectByUserUniqueIds(myFriendsUniqueIds); if (CollectionUtils.isEmpty(userConfigDTOS)) { throw new CommonAssertException(ApplicationCodes.USER_CONFIG_NOT_EXIST); } Map userConfigMap = userConfigDTOS.stream().collect(Collectors.toMap(it -> it.getUserUniqueId(), it -> it)); List userDTOList = Lists.newArrayList(); myFriendUsers.stream().forEach(user -> { UserConfigDTO userConfig = userConfigMap.get(user.getUserUniqueId()); UserDTO userDTO = new UserDTO(); userDTO.setUserUniqueId(user.getUserUniqueId()); userDTO.setAvatar(ossUtil.getUrl(ossUtil.getAvatarBucketName(), user.getUserUniqueId(), CommonConstant.AVATAR_TTL)); userDTO.setName(getDisplayText(Objects.equals(userConfig.getVisbleName(), YesNoEnum.YES.getCode()), user.getName())); userDTO.setAge(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()) ? user.getAge() : null); userDTO.setSex(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()) ? user.getSex() : null); userDTO.setFeelingStatus(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()) ? user.getFeelingStatus() : null); String displayBirthdayText = getDisplayText(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()), user.getBirthday()); userDTO.setBirthday(displayBirthdayText); userDTO.setCurrentDynamic(getDisplayText(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()), user.getCurrentDynamic())); String currentHome = areaUtil.getFormartDisplayArea(user.getCurrentHome()); if (StringUtils.isNotEmpty(currentHome) && currentHome.split(AREA_SPLIT).length == 4) { String[] split = currentHome.split(AREA_SPLIT); currentHome = split[0] + "," + split[2]; } String forMartFamilyHome = ""; if (StringUtils.isNotEmpty(user.getOriginalFamilyHome())) { forMartFamilyHome = areaUtil.getFormartDisplayArea(user.getOriginalFamilyHome()); if (StringUtils.isNotEmpty(forMartFamilyHome) && forMartFamilyHome.split(AREA_SPLIT).length == 4) { String[] split = forMartFamilyHome.split(AREA_SPLIT); forMartFamilyHome = split[0] + "," + split[2]; } } userDTO.setNickName(getDisplayText(Objects.equals(userConfig.getVisbleBase(), YesNoEnum.YES.getCode()), user.getNickName())); userDTO.setWeixin(getDisplayText(Objects.equals(userConfig.getVisbleWeixin(), YesNoEnum.YES.getCode()), user.getWeixin())); userDTO.setQq(getDisplayText(Objects.equals(userConfig.getVisbleQq(), YesNoEnum.YES.getCode()), user.getQq())); userDTO.setPhone(getDisplayText(Objects.equals(userConfig.getVisblePhone(), YesNoEnum.YES.getCode()), user.getPhone())); userDTO.setApprovalLevel(user.getApprovalLevel()); userDTO.setWork(user.getWork()); userDTO.setProfile(String.format("%s\n", userDTO.toString())); userDTOList.add(userDTO); }); PageDTO> pageDTO = new PageDTO<>(); pageDTO.setData(userDTOList); pageDTO.setTotal((int) friendPage.getTotal()); pageDTO.setPageSize((int) friendPage.getSize()); pageDTO.setPageNo((int) friendPage.getCurrent()); pageDTO.isHasMore(pageDTO.getTotal(), pageDTO.getPageNo(), pageDTO.getPageSize()); return pageDTO; } return new PageDTO<>(); } @Override public String createInvite(String currentUserUniqueId) { TUser tUser = userHelper.selectByUserUniqueId(currentUserUniqueId); Optional.ofNullable(tUser).orElseThrow(() -> new CommonAssertException(ApplicationCodes.USER_NOT_EXIST)); String substring = tUser.getPhone().substring(7, 11); String inviteCodeKey = CommonConstant.USER_INVITE_CODE_KEY + currentUserUniqueId; Object code = redisUtil.get(inviteCodeKey); if (Objects.isNull(code)) { String randomString = SampleRandomUtil.getRandomString(currentUserUniqueId, 4); String validateCodeValue = substring + randomString; redisUtil.set(inviteCodeKey, validateCodeValue, 60 * 5); redisUtil.set(CommonConstant.INVITE_CODE + validateCodeValue, currentUserUniqueId, 60 * 5); return validateCodeValue; } return code.toString(); } @Override public boolean validateInvite(String code) { if (StringUtils.isEmpty(code)) { return false; } if (code.length() != 8) { return false; } Object inviteUserUniqueId = redisUtil.get(CommonConstant.INVITE_CODE + code); if (Objects.isNull(inviteUserUniqueId)) { return false; } //code:前四位是邀请用户手机号后四位 String validateCode = code.substring(4, 8); char[] chars = validateCode.toCharArray(); CharSequence inviteCodeCharSequence = (CharSequence) inviteUserUniqueId; for (int i = 0; i < chars.length; i++) { if (!StringUtils.contains(inviteCodeCharSequence, chars[i])) { return false; } } return true; } @Override public String getInviteCodeValueToUserUniqueId(String code) { if (StringUtils.isEmpty(code)) { return ""; } Object inviteCode = redisUtil.get(CommonConstant.INVITE_CODE + code); if (Objects.isNull(inviteCode)) { return ""; } return inviteCode.toString(); } @Override public String getVerificationCodeByPhone(String phone) { Optional.ofNullable(phone).orElseThrow(() -> new CommonAssertException(ApplicationCodes.USER_PHONE_NOT_EMPTY)); String defaultKey = CommonConstant.GET_LOGIN_VERIFICATION_CODE_KEY + StringUtils.trim(phone); Object code = redisUtil.get(defaultKey); if (Objects.nonNull(code)) { return "验证码已发送至,您的手机请查收."; } else { try { String randomString = SampleRandomUtil.getRandomString(4); // String addSmsTemplate = smsUtil.addSmsTemplate(); String bizId = smsUtil.sendSms(phone, "SMS_217881424", randomString); String result = smsUtil.querySendDetails(bizId); if (result.contains("OK")) { redisUtil.set(defaultKey, randomString, 60 * 5); } return "验证码已发送至,您的手机请查收."; } catch (Exception e) { log.info("生成注册校验码失败, {}", e); throw new CommonAssertException(ApplicationCodes.GET_VERIFICATION_CODE_IS_ERROR); } } } private String getDisplayText(boolean isVisible, String lab) { if (isVisible) { if (StringUtils.isNotEmpty(lab)) { return lab; } else { return "未填写"; } } else { return "保密"; } } }

2. 重构后代码片段

  • UserController.java

/**
 * @author x
 */
@RestController
@RequestMapping("/user")
@Api(value = "用户接口", tags = "用户接口")
public class UserController {

    @Autowired
    private UserQueryService                 userQueryService;
    @Autowired
    private UserApplicationService           userApplicationService;
    @Autowired
    private AuthenticationApplicationService authenticationApplicationService;

    @ApiOperation(value = "登录", notes = "参数: LoginCommand")
    @PostMapping("/login")
    public ResultDTO login(@Valid @RequestBody LoginCommand loginCommand) {
        return authenticationApplicationService.login(loginCommand);
    }

    @ApiOperation(value = "注册", notes = "参数: UserDTO")
    @PostMapping("/register")
    public ResultDTO register(@Valid @RequestBody RegisterCommand registerCommand) {
        return new ResultDTO(userApplicationService.register(registerCommand));
    }

    @ApiOperation(value = "创建邀请码", notes = "参数: 无")
    @PostMapping("/createInvite")
    public ResultDTO createInvite() {
        return new ResultDTO(userApplicationService.createInvite());
    }

    @ApiOperation(value = "验证登录验证码", notes = "参数: 无")
    @PostMapping("/sendLoginValidateCodeByPhone")
    public ResultDTO sendLoginValidateCodeByPhone(@Valid
                                                  @Size(max = 11, min = 11)
                                                  @NotEmpty String phone) {
        return new ResultDTO(userApplicationService.sendLoginValidateCodeByPhone(phone));
    }

    @ApiOperation(value = "查询当前登录人信息", notes = "参数: 无")
    @GetMapping("/current/query")
    public ResultDTO query() {
        return new ResultDTO(userQueryService.queryCurrentUser());
    }
}

  • UserApplicationServiceImpl.java
/**
 * @author xujie
 * @since 2022-01-03
 */
@Service
public class UserApplicationServiceImpl implements UserApplicationService {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private RedisUtil      redisUtil;
    @Autowired
    private AliSmsUtil     smsUtil;

    @Override
    public String createInvite() {
        return new UserService(userRepository, redisUtil, smsUtil)
                .createInvite();
    }

    @Override
    public boolean register(RegisterCommand registerCommand) {
        User user = UserDTOAssembler.toUser(registerCommand);
        user.setPassword(new Password(user.getPassword().getMd5Password()));
        user.setStatus(new Status(Status.StatusEnum.NORMAL));
        UserService userService = new UserService(userRepository, redisUtil, smsUtil);
        return userService.register(user, registerCommand.getInviteCode());
    }

    @Override
    public String sendLoginValidateCodeByPhone(String phone) {
        return new UserService(redisUtil, smsUtil)
                .sendLoginVerificationCodeByPhone(phone);
    }
}

  • UserService.java
/**
 * DomainService
 *
 * @author xujie
 * @since 2022-01-03
 **/
@Slf4j
public class UserService {

    private UserRepository userRepository;
    private RedisUtil      redisUtil;
    private AliSmsUtil     smsUtil;

    public UserService(UserRepository userRepository, RedisUtil redisUtil, AliSmsUtil smsUtil) {
        this.userRepository = userRepository;
        this.redisUtil = redisUtil;
        this.smsUtil = smsUtil;
    }

    public UserService(RedisUtil redisUtil, AliSmsUtil smsUtil) {
        this.redisUtil = redisUtil;
        this.smsUtil = smsUtil;
    }

    public String createInvite() {
        String                    userUniqueId              = UserCurrentUtil.getUserUniqueId();
        User                      user                      = userRepository.find(new UserUniqueId(userUniqueId));
        CreateInviteSpecification createInviteSpecification = new CreateInviteSpecification();
        if (createInviteSpecification.isSatisfiedBy(user)) {
            String substring     = user.getPhone().getInviteString();
            String inviteCodeKey = UserConstant.USER_INVITE_CODE_KEY + userUniqueId;
            Object code          = redisUtil.get(inviteCodeKey);
            if (Objects.isNull(code)) {
                String randomString      = SampleRandomUtil.getRandomString(userUniqueId, 4);
                String validateCodeValue = substring + randomString;
                redisUtil.set(inviteCodeKey, validateCodeValue, 60 * 5);
                redisUtil.set(UserConstant.INVITE_CODE + validateCodeValue, userUniqueId, 60 * 5);
                return validateCodeValue;
            }
            return code.toString();
        }
        return "";
    }


    public String sendLoginVerificationCodeByPhone(String phone) {
        Optional.ofNullable(phone).orElseThrow(() -> new CommonAssertException(UserConstant.USER_PHONE_NOT_EMPTY));
        String defaultKey = UserConstant.GET_LOGIN_VERIFICATION_CODE_KEY + StringUtils.trim(phone);
        Object code       = redisUtil.get(defaultKey);
        if (Objects.nonNull(code)) {
            return "验证码已发送至,您的手机请查收.";
        } else {
            try {
                String randomString = SampleRandomUtil.getRandomString(4);
                String bizId        = smsUtil.sendSms(phone, "SMS_217881424", randomString);
                String result       = smsUtil.querySendDetails(bizId);
                if (result.contains("OK")) {
                    redisUtil.set(defaultKey, randomString, 60 * 5);
                }
                return "验证码已发送至,您的手机请查收.";
            } catch (Exception e) {
                log.info("生成注册校验码失败, {}", e);
                throw new CommonAssertException(UserConstant.GET_VERIFICATION_CODE_IS_ERROR);
            }
        }
    }

    public boolean register(User user, String inviterCode) {
        UserCreateNotExistSpecification userCreateNotExistSpecification =
                new UserCreateNotExistSpecification(userRepository);
        RegisterInviteCodeSpecification registerInviteCodeSpecification =
                new RegisterInviteCodeSpecification(redisUtil, inviterCode);
        boolean satisfiedBy = userCreateNotExistSpecification
                .and(registerInviteCodeSpecification)
                .isSatisfiedBy(user);
        if (satisfiedBy) {
            return userRepository.store(user);
        }
        return false;
    }
}

重构心得

1. 代码量减少,层次清晰

2. 逻辑清晰,代码可读性强

3. 减少出错率等