【异常】一个Excel导入功能竟然会出现了504 Gateway Time-out!
@Service
@Slf4j
@AllArgsConstructor
public class ThemeActivityUserServiceImpl extends ServiceImpl<ThemeActivityUserMapper, ThemeActivityUser> implements ThemeActivityUserService {
private static final int MAX_STRING_100 = 100;
private static final int MAX_STRING_30 = 30;
private static final Integer ONE = 1;
private static final String PHONE_REGEX = "^1[3|4|5|6|7|8|9][0-9]\\d{4,8}$";
private final UserInfoMapper userInfoMapper;
private final ThemeActivityGiftBindingService bindingService;
//导入目标用户数据
@Override
@Transactional(rollbackFor = Exception.class)
public String importTargetUser(List<ThemeActivityTargetUser> targetUserList, Boolean updateFlag, String giftIds, String activityId) throws Exception {
StringBuilder successMsg = new StringBuilder();
StringBuilder failureMsg = new StringBuilder();
// 创建一个外部的final变量来存储计数
final int[] failureNum = {0};
ArrayList<ThemeActivityUser> themeActivityUsers = new ArrayList<>();
ArrayList<String> targetWorkNoList = new ArrayList<>();
targetUserList.stream().forEach(targetUser -> {
String workNo = targetUser.getWorkNo();
String phone = targetUser.getPhone();
String userName = targetUser.getUserName();
Integer receiveNum = targetUser.getReceiveNum();
String company = targetUser.getCompany();
String department = targetUser.getDepartment();
if (StrUtil.hasBlank(workNo, phone, userName) || ObjectUtil.hasNull(receiveNum)) {
// 在lambda表达式中修改外部变量的值
failureNum[0]++;
failureMsg.append("<br/>").append("目标用户数据的工号/手机号/用户名称/领取数量不能为空,请核对导入名单!");
return;
}
if (receiveNum < ONE) {
failureNum[0]++;
failureMsg.append("<br/>").append("目标用户数据的领取数量小于1,请核对导入名单!");
return;
}
if (workNo.length() > MAX_STRING_30) {
failureNum[0]++;
failureMsg.append("<br/>").append("目标用户数据【").append(workNo).append("】导入失败,用户工号过长无法导入");
return;
}
if (userName.length() > MAX_STRING_30) {
failureNum[0]++;
failureMsg.append("<br/>").append("目标用户数据【").append(userName).append("】导入失败,用户姓名过长无法导入");
return;
}
if (phone.length() > MAX_STRING_30) {
failureNum[0]++;
failureMsg.append("<br/>").append("目标用户数据【").append(phone).append("】导入失败,用户手机号过长无法导入");
return;
}
if (!phone.matches(PHONE_REGEX)) {
failureNum[0]++;
failureMsg.append("<br/>").append("目标用户数据【").append(phone).append("】导入失败,手机号码格式不正确");
return;
}
if (company.length() > MAX_STRING_100) {
failureNum[0]++;
failureMsg.append("<br/>").append("目标用户数据【").append(company).append("】导入失败,公司信息过长无法导入");
return;
}
if (department.length() > MAX_STRING_100) {
failureNum[0]++;
failureMsg.append("<br/>").append("目标用户数据【").append(department).append("】导入失败,部门信息过长无法导入");
return;
}
ThemeActivityUser themeActivityUser = getThemeActivityUser(giftIds, activityId, targetUser);
themeActivityUsers.add(themeActivityUser);
targetWorkNoList.add(workNo);
});
//判断是否有异常
if (failureNum[0] > 0) {
log.error("很抱歉,导入失败!failureMsg=【{}】", failureMsg.toString());
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum[0] + " 条数据格式不正确,错误如下:");
throw new Exception(failureMsg.toString());
}
//校验活动目标用户数据在Excel中是否存在重复数据
Pair<Boolean, String> repeatResultExcel = this.checkRepeatImportUserInExcel(targetWorkNoList, activityId);
if (repeatResultExcel.getKey().equals(Boolean.FALSE)) {
String msg = "<br/>" + "很抱歉,导入失败!活动目标用户数据在Excel中存在重复数据,请先去除重复性数据,再重新导入,不会操作请联系管理员!";
failureMsg.append(msg);
log.error(msg);
throw new Exception(failureMsg.toString());
}
//校验活动目标用户数据在数据库中是否存在重复数据
Pair<Boolean, String> repeatResult = this.checkRepeatImportUserInDb(targetWorkNoList, activityId);
if (repeatResult.getKey().equals(Boolean.FALSE)) {
String msg = "<br/>" + "很抱歉,导入失败!活动目标用户数据在数据库中存在重复数据,请先去除重复性数据,再重新导入,不会操作请联系管理员!工号列表如下: " + repeatResult.getValue();
failureMsg.append(msg);
log.error(msg);
throw new Exception(failureMsg.toString());
}
boolean saveFlag = this.saveBatch(themeActivityUsers);
if (Boolean.FALSE.equals(saveFlag)) {
String msg = "<br/>" + "很抱歉,导入失败!活动目标用户数据导入失败,请联系管理员! ";
failureMsg.append(msg);
log.error(msg);
throw new Exception(failureMsg.toString());
}
int successNum = themeActivityUsers.size();
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条活动目标用户数据导入成功");
//异步初始化礼品与活动的绑定管理
ThreadUtil.execAsync(() -> bindingService.initThemeActivityGiftBinding(giftIds, activityId));
//异步完成用户ID的导入
ThreadUtil.execAsync(() -> this.updateUserId(activityId));
return successMsg.toString();
}
//校验并获取Excel中重复导入的用户总数
//校验名单中是否有重复数据
private Pair<Boolean, String> checkRepeatImportUserInExcel(ArrayList<String> targetWorkNoList, String activityId) {
Set<String> set = new HashSet(targetWorkNoList);
if (set.size() < targetWorkNoList.size()) {
log.error("checkRepeatImportUser导入的名单中,存在重复数据!");
return new Pair<>(Boolean.FALSE, "导入的名单中,存在重复数据!请检查!");
}
log.info("checkRepeatImportUserInExcel不存在重复导入的数据");
return new Pair<>(Boolean.TRUE, null);
}
//校验并获取数据库中重复导入的工号列表
//重复用户数据的过滤与查询
private Pair<Boolean, String> checkRepeatImportUserInDb(ArrayList<String> targetWorkNoList, String activityId) {
List<String> existWorkNoList = new ArrayList<>();
LambdaQueryWrapper<ThemeActivityUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(ThemeActivityUser::getActivityId, activityId);
List<Map<String, Object>> maps = baseMapper.selectMaps(lambdaQueryWrapper);
if (CollUtil.isEmpty(maps)) {
log.info("checkRepeatImportUserInDb不存在重复导入的数据");
return new Pair<>(Boolean.TRUE, null);
}
if (ObjectUtil.isNotEmpty(maps)) {
for (Map<String, Object> map : maps) {
String workNo = MapUtil.getStr(map, "work_no");
existWorkNoList.add(workNo);
}
}
if (CollUtil.containsAny(targetWorkNoList, existWorkNoList)) {
//使用方法获取两个集合的交集。
Collection<String> repeatList = CollUtil.intersection(targetWorkNoList, existWorkNoList);
return new Pair<>(Boolean.FALSE, JSONUtil.toJsonStr(repeatList));
}
log.info("checkRepeatImportUserInDb不存在重复导入的数据");
return new Pair<>(Boolean.TRUE, null);
}
//封装导入用户的实体类
private ThemeActivityUser getThemeActivityUser(String giftIds, String activityId, ThemeActivityTargetUser targetUser) {
ThemeActivityUser themeActivityUser = new ThemeActivityUser();
themeActivityUser.setId("1" + RandomUtil.randomNumbers(14));
themeActivityUser.setActivityId(activityId);
//设置用户能够领取的礼品列表
themeActivityUser.setGiftIds(giftIds);
themeActivityUser.setCompany(targetUser.getCompany().trim());
themeActivityUser.setDepartment(targetUser.getDepartment().trim());
themeActivityUser.setPhone(targetUser.getPhone().trim());
themeActivityUser.setUserName(targetUser.getUserName().trim());
themeActivityUser.setWorkNo(targetUser.getWorkNo().trim());
themeActivityUser.setReceiveNum(targetUser.getReceiveNum());
themeActivityUser.setUserStatus(ThemeActivityUserStatusEnum.TO_BE_RECEIVED.getValue());
themeActivityUser.setCreateTime(new Date());
themeActivityUser.setCreateBy(SecurityUtils.getUser().getUsername());
return themeActivityUser;
}
//更新用戶的UserID
private void updateUserId(String activityId) {
LambdaQueryWrapper<ThemeActivityUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ThemeActivityUser::getActivityId, activityId);
wrapper.isNull(ThemeActivityUser::getUserId);
List<ThemeActivityUser> themeActivityUserList = baseMapper.selectList(wrapper);
themeActivityUserList.forEach(themeActivityUser -> {
String workNo = themeActivityUser.getWorkNo();
String phone = themeActivityUser.getPhone();
String userId = getUserIdByWorkNoAndPhone(workNo, phone);
themeActivityUser.setUserId(userId);
});
this.saveOrUpdateBatch(themeActivityUserList);
}
//根据工号+手机号锁定用户的UserID
private String getUserIdByWorkNoAndPhone(String workNo, String phone) {
log.info("getUserIdByWorkNoAndPhone, workNo = {},phone ={}", workNo, phone);
List<UserInfo> userInfoList = userInfoMapper.getUserIdByWorkNoAndPhone(workNo, phone);
if (CollUtil.isNotEmpty(userInfoList)) {
return userInfoList.get(0).getId();
}
return null;
}
}