Commit c2cc1782 authored by Aleyn's avatar Aleyn

Merge branch 'lyg_dev' into 'master'

别名批量推送

See merge request !33
parents 8ad52600 9b45a31c
...@@ -350,4 +350,19 @@ public class CommonUtil { ...@@ -350,4 +350,19 @@ public class CommonUtil {
return null; return null;
} }
} }
/**
* 获分组次数
* @param total 总长度
* @param size 每个分组长度
* @return 分组次数
*/
public static Integer getGroupCount(Integer total, Integer size) {
int groupCount = total / size;
if (total % size != 0) {
groupCount = groupCount + 1;
}
return groupCount;
}
} }
...@@ -3,14 +3,21 @@ package com.weface.common.validator; ...@@ -3,14 +3,21 @@ package com.weface.common.validator;
import com.weface.code.CommonResult; import com.weface.code.CommonResult;
import com.weface.code.ResultCode; import com.weface.code.ResultCode;
import com.weface.dto.InformForm; import com.weface.dto.InformForm;
import com.weface.dto.MultiInformForm;
import com.weface.dto.MultiMsgDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
/** /**
* @author : Administrator * @author : Administrator
* @date : 2022/4/21 14:28 * @date : 2022/4/21 14:28
*/ */
@Slf4j
public class ValidatorParam { public class ValidatorParam {
/** /**
...@@ -61,4 +68,34 @@ public class ValidatorParam { ...@@ -61,4 +68,34 @@ public class ValidatorParam {
return null; return null;
} }
/**
* 校验推送参数
*
* @param informForm 推送参数
* @return 核验结果
*/
public static CommonResult validBatchPushParams(MultiInformForm informForm) {
List<MultiMsgDTO> msgList = informForm.getMsgList();
List<MultiMsgDTO> blankTitleList = msgList.stream().filter(x -> StringUtils.isBlank(x.getTitle())).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(blankTitleList)) {
log.error("msgList中含title为空的消息: param=[{}]", informForm);
return CommonResult.validateFailed("msgList中含title为空的消息");
}
List<MultiMsgDTO> blankContentList = msgList.stream().filter(x -> StringUtils.isBlank(x.getContent())).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(blankContentList)) {
log.error("msgList中含content为空的消息: param=[{}]", informForm);
return CommonResult.validateFailed("msgList中含content为空的消息");
}
List<MultiMsgDTO> emptyAliasList = msgList.stream().filter(x -> x.getAlias() == null || x.getAlias().length == 0).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(emptyAliasList)) {
log.error("msgList中含alias为空的消息: param=[{}]", informForm);
return CommonResult.validateFailed("msgList中含alias为空的消息");
}
return null;
}
} }
...@@ -10,17 +10,24 @@ import cn.hutool.http.HttpUtil; ...@@ -10,17 +10,24 @@ import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.weface.code.CommonResult; import com.weface.code.CommonResult;
import com.weface.common.utils.CommonUtil;
import com.weface.common.utils.Constant; import com.weface.common.utils.Constant;
import com.weface.common.utils.Model; import com.weface.common.utils.Model;
import com.weface.dto.InformForm; import com.weface.dto.InformForm;
import com.weface.dto.MultiInformForm;
import com.weface.dto.MultiMsgDTO;
import com.weface.service.PushLogService; import com.weface.service.PushLogService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
/** /**
* @author : Administrator * @author : Administrator
...@@ -42,6 +49,15 @@ public class MobPushService { ...@@ -42,6 +49,15 @@ public class MobPushService {
@Autowired @Autowired
private PushLogService pushLogService; private PushLogService pushLogService;
/**
* 批量推送最大消息体数量
*/
private static final int MAX_ITEM_SIZE = 20;
/**
* 批量推送的消息体内最大推送设备数
*/
private static final int MAX_ALIAS = 200;
/** /**
* mob 推送 * mob 推送
* *
...@@ -84,7 +100,7 @@ public class MobPushService { ...@@ -84,7 +100,7 @@ public class MobPushService {
request.put("groupId", target.getValue()); request.put("groupId", target.getValue());
String body = generalPost(request, pushUrl); String body = generalPost(request, pushUrl);
if (body != null) { if (body != null) {
pushLogService.saveMobLog(JSONObject.parseObject(body), informForm); pushLogService.saveMobLog(JSONObject.parseObject(body), informForm, false);
return CommonResult.success(); return CommonResult.success();
} }
return null; return null;
...@@ -107,14 +123,58 @@ public class MobPushService { ...@@ -107,14 +123,58 @@ public class MobPushService {
} }
/** /**
* mob批量推送 * mob别名批量推送
* * 与袤博技术人员确认:建议一个推送任务设置20 items,一个items可以设置200个推送设备
* @param informForm 推送内容 * @param multiInformForm 推送内容
* @param target 推送目标
* @return 执行结果 * @return 执行结果
*/ */
public Model batchMobPush(InformForm informForm, Constant.PushTarget target) { public CommonResult batchMobPush(MultiInformForm multiInformForm) {
// 消息体数量
List<MultiMsgDTO> itemList = multiInformForm.getMsgList();
List<MultiMsgDTO> splitItemList = new ArrayList<MultiMsgDTO>();
// 判断每个消息体中的推送设备数是否达到最大限制,
// 如果达到最大限制,则从中分割出N个小于最大限制的消息体,并将其添加到原始的消息体数量中
for (MultiMsgDTO msg : itemList) {
if (msg.getAlias().length > MAX_ALIAS) {
// 从当前的消息体中拆分出N个小于最大限制的消息体
List<MultiMsgDTO> subItemList = splitExceedLimitMsg(msg);
// 将新的消息体集合统一放到的新的消息体集合中
splitItemList.addAll(subItemList);
} else {
msg.setItemId(IdUtil.fastUUID());
}
}
if (!CollectionUtils.isEmpty(splitItemList)) {
// 将所有划分后的消息体放到原始的消息体集合中
itemList.addAll(splitItemList);
}
// 删除没有itemId的元素(超过最大限制的元素)
itemList.removeIf(x -> StringUtils.isBlank(x.getItemId()));
// 判断消息体的数量是否达到上限
// 如果达到最大限制,则将其划分成N个小于最大限制的推送任务
if (itemList.size() > MAX_ITEM_SIZE) {
List<MultiInformForm> informForms = splitExceedLimitForm(multiInformForm);
batchMobPushExecute(informForms);
} else {
// 直接执行当前推送任务
batchMobPushExecute(Collections.singletonList(multiInformForm));
}
return CommonResult.success();
}
/**
* 执行批量推送
* @param multiInformFormList 推送任务集合
*/
public void batchMobPushExecute(List<MultiInformForm> multiInformFormList) {
String pushUrl = "http://api.push.mob.com/v3/push/createMulti"; String pushUrl = "http://api.push.mob.com/v3/push/createMulti";
for (MultiInformForm form : multiInformFormList) {
Map<String, Object> request = new HashMap<>(2); Map<String, Object> request = new HashMap<>(2);
Map<String, Object> pushWork = new HashMap<>(); Map<String, Object> pushWork = new HashMap<>();
...@@ -123,34 +183,117 @@ public class MobPushService { ...@@ -123,34 +183,117 @@ public class MobPushService {
//Mob-appkey //Mob-appkey
pushWork.put("appkey", APP_KEY); pushWork.put("appkey", APP_KEY);
//推送展示细节配置 //推送展示细节配置
InformForm informForm = new InformForm();
BeanUtils.copyProperties(form, informForm);
Map<String, Object> pushNotify = getBatchPushNotify(informForm); Map<String, Object> pushNotify = getBatchPushNotify(informForm);
pushWork.put("pushNotify", pushNotify); pushWork.put("pushNotify", pushNotify);
//link 相关打开配置 //link 相关打开配置
Map<String, Object> pushForward = getPushForward(); Map<String, Object> pushForward = getPushForward();
pushWork.put("pushForward", pushForward); pushWork.put("pushForward", pushForward);
//是否重复推送
//pushWork.put("repate", repate);
//repate 重复记录原始ID
//pushWork.put("parentId", parentId);
//groupId: AB分组测试ID //groupId: AB分组测试ID
pushWork.put("groupId", target.getValue()); pushWork.put("groupId", Constant.PushTarget.ALIAS.getKey());
request.put("pushWork", pushWork); request.put("pushWork", pushWork);
//推送目标
String[] split; MultiMsgDTO[] items = form.getMsgList().toArray(new MultiMsgDTO[form.getMsgList().size()]);
String cid = informForm.getCid(); request.put("items", items);
if (cid.contains(",")) {
split = cid.split(",");
} else {
split = new String[]{cid};
}
Map<String, Object> items = getItems(split, informForm.getTitle(), informForm.getBody(), target.getKey());
request.put("items", new Object[]{items});
String body = generalPost(request, pushUrl); String body = generalPost(request, pushUrl);
log.info("批量推送结果:{}", body); log.info("批量推送结果:{}", body);
if (body != null) { if (body != null) {
return Model.ok(); batchMobPushSaveLog(form, body);
}
}
}
public void batchMobPushSaveLog(MultiInformForm multiInformForm, String resultBody) {
for (MultiMsgDTO msg : multiInformForm.getMsgList()) {
InformForm informForm = new InformForm();
BeanUtils.copyProperties(multiInformForm, informForm);
informForm.setBody(msg.getContent());
String cid = String.join(",", msg.getAlias());
informForm.setCid(cid);
informForm.setMessageTemplate(3);
pushLogService.saveMobLog(JSONObject.parseObject(resultBody), informForm, true);
} }
return Model.error(); }
/**
* 将超出 最大推送设备数的消息体进行分割
* @param msg 消息体
* @return 分割后的消息体的集合
*/
private List<MultiMsgDTO> splitExceedLimitMsg(MultiMsgDTO msg) {
// 计算最终从拆分的消息体的数量
Integer itemCount = CommonUtil.getGroupCount(msg.getAlias().length, MAX_ALIAS);
// 定义返回的消息体集合
List<MultiMsgDTO> itemList = new ArrayList<MultiMsgDTO>(itemCount);
// 取出所有原消息体中的推送设备
List<String> alias = new ArrayList<>(Arrays.asList(msg.getAlias()));
// 将推送设备进行拆分
for (int i = 0; i < itemCount; i++) {
// 当前子消息体内的推送设备列表
List<String> subAlias = new ArrayList<>();
if (i == itemCount - 1) {
subAlias = alias.subList(MAX_ALIAS * i, alias.size() - 1);
subAlias.add(alias.get(alias.size() - 1));
} else {
subAlias = alias.subList(MAX_ALIAS * i, (MAX_ALIAS * i) + MAX_ALIAS);
}
MultiMsgDTO item = new MultiMsgDTO();
BeanUtils.copyProperties(msg, item);
item.setAlias(subAlias.toArray(new String[subAlias.size()]));
item.setItemId(IdUtil.fastUUID());
itemList.add(item);
}
return itemList;
}
/**
* 将超出 最大推送消息体数量的任务进行分割
* @param form 推送任务
* @return 分割后的推送任务的集合
*/
private List<MultiInformForm> splitExceedLimitForm(MultiInformForm form) {
// 计算最终从拆分的推送任务的数量
Integer formCount = CommonUtil.getGroupCount(form.getMsgList().size(), MAX_ITEM_SIZE);
// 定义返回的推送任务集合
List<MultiInformForm> subFormList = new ArrayList<MultiInformForm>(formCount);
// 取出所有原推送任务中的消息体
List<MultiMsgDTO> msgList = form.getMsgList();
// 将消息体进行拆分
for (int i = 0; i < formCount; i++) {
MultiInformForm subForm = new MultiInformForm();
BeanUtils.copyProperties(form, subForm);
// 当前子推送任务内的消息体
// List<MultiMsgDTO> subMsgList = new ArrayList<>();
if (i == formCount - 1) {
List<MultiMsgDTO> subMsgList = msgList.subList(MAX_ITEM_SIZE * i, msgList.size() - 1);
// 不再对原集合操作,避免出现java.util.ConcurrentModificationException异常
if (subMsgList.size() == 0) {
subForm.setMsgList(new ArrayList<>(Collections.singletonList(msgList.get(msgList.size() - 1))));
}
} else {
List<MultiMsgDTO> subMsgList = msgList.subList(MAX_ITEM_SIZE * i, (MAX_ITEM_SIZE * i) + MAX_ITEM_SIZE);
subForm.setMsgList(subMsgList);
}
subFormList.add(subForm);
}
return subFormList;
} }
/** /**
...@@ -197,22 +340,6 @@ public class MobPushService { ...@@ -197,22 +340,6 @@ public class MobPushService {
return false; return false;
} }
private Map<String, Object> getItems(String[] target, String title, String content, Integer pushType) {
Map<String, Object> items = new HashMap<>();
items.put("itemId", IdUtil.fastUUID());
//items.put("workNo", workNo);
//items.put("appPackages", new String[]{});
if (pushType.equals(Constant.PushTarget.ALIAS.getKey())) {
items.put("alias", target);
}
if (pushType.equals(Constant.PushTarget.RIDS.getKey())) {
items.put("rids", target);
}
items.put("title", title);
items.put("content", content);
return items;
}
/** /**
* 批量推送 * 批量推送
* *
...@@ -489,18 +616,27 @@ public class MobPushService { ...@@ -489,18 +616,27 @@ public class MobPushService {
} else { } else {
request = JSONObject.toJSONString(map); request = JSONObject.toJSONString(map);
} }
log.error("mob推送内容:{}", request); log.info("mob推送内容:{}", request);
HttpRequest post = HttpUtil.createPost(url); HttpRequest post = HttpUtil.createPost(url);
post.header("Content-Type", "application/json"); post.header("Content-Type", "application/json");
post.header("key", APP_KEY); post.header("key", APP_KEY);
post.header("sign", getSign(request)); post.header("sign", getSign(request));
String body = post.body(request).execute().body(); String body = post.body(request).execute().body();
log.error("mob推送结果:{}", body); log.info("mob推送结果:{}", body);
if (JSONUtil.isJson(body)) { if (JSONUtil.isJson(body)) {
JSONObject json = JSONObject.parseObject(body); JSONObject json = JSONObject.parseObject(body);
if (json.containsKey("status") && json.getInteger("status").equals(200)) if (json.containsKey("status") && json.getInteger("status").equals(200)) {
JSONObject res = (JSONObject) JSONObject.parseObject(body).get("res");
if (!res.containsKey("errors")) {
return body; return body;
} }
Object errors = res.get("errors");
if (ObjectUtils.isEmpty(errors)) {
return body;
}
}
}
return null; return null;
} }
......
...@@ -9,11 +9,13 @@ import com.weface.component.GeTuiService; ...@@ -9,11 +9,13 @@ import com.weface.component.GeTuiService;
import com.weface.component.MobPushService; import com.weface.component.MobPushService;
import com.weface.dto.InformForm; import com.weface.dto.InformForm;
import com.weface.dto.MsgDTO; import com.weface.dto.MsgDTO;
import com.weface.dto.MultiInformForm;
import com.weface.dto.PushDTO; import com.weface.dto.PushDTO;
import com.weface.service.PushService; import com.weface.service.PushService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
...@@ -116,4 +118,18 @@ public class PushController { ...@@ -116,4 +118,18 @@ public class PushController {
return CommonResult.success(result, "推送成功"); return CommonResult.success(result, "推送成功");
} }
} }
/**
* 别名批量推送
*/
@PostMapping("/batch/alias")
public CommonResult batchMobPush(@RequestBody @Validated MultiInformForm multiInformForm) {
CommonResult result = ValidatorParam.validBatchPushParams(multiInformForm);
if (result != null) {
return result;
}
return mobPushService.batchMobPush(multiInformForm);
}
} }
package com.weface.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @Author: lyg
* @Description:
* @Date: 2023/5/10 16:03
**/
@Data
public class MultiInformForm {
/**
* 推送的消息体数组
*/
@NotEmpty(message = "消息列表不能为空")
private List<MultiMsgDTO> msgList;
/**
* 跳转url
*/
@NotBlank(message = "url不能为空")
private String url;
/**
* 推送类型 0:h5 1:原生,默认h5
*/
@NotNull(message = "pushType不能为空")
private Integer pushType;
/**
* 推送平台:kksh,kksb,kkwj,kkmz
*/
@NotBlank(message = "equipmentType不能为空")
private String equipmentType;
}
package com.weface.dto;
import lombok.Data;
/**
* @Author: lyg
* @Description:
* @Date: 2023/5/10 16:10
**/
@Data
public class MultiMsgDTO {
/**
* item id(用户自自定义生成且唯一、不能重复)
*/
private String itemId;
/**
* 推送目标, cid的集合,如:[kksh_59354, kksh_59355, kksh_59356]
*/
private String [] alias;
/**
* 消息标题
*/
private String title;
/**
* 消息内容
*/
private String content;
/**
* 推送任务的 workNo 非必填
*/
private String workNo;
/**
* 包名列表 非必填
*/
private String appPackages;
}
...@@ -28,8 +28,9 @@ public interface PushLogService extends IService<PushLogEntity> { ...@@ -28,8 +28,9 @@ public interface PushLogService extends IService<PushLogEntity> {
* *
* @param data 返回数据 * @param data 返回数据
* @param informForm 推送数据 * @param informForm 推送数据
* @param isBatch 是否为批量推送
*/ */
public void saveMobLog(JSONObject data, InformForm informForm); public void saveMobLog(JSONObject data, InformForm informForm, boolean isBatch);
/** /**
* 查询日志 * 查询日志
......
...@@ -50,10 +50,17 @@ public class PushLogServiceImpl extends ServiceImpl<PushLogDao, PushLogEntity> i ...@@ -50,10 +50,17 @@ public class PushLogServiceImpl extends ServiceImpl<PushLogDao, PushLogEntity> i
} }
@Override @Override
public void saveMobLog(JSONObject data, InformForm informForm) { public void saveMobLog(JSONObject data, InformForm informForm, boolean isBatch) {
try { try {
Long id = SnowIdUtil.nextId(); Long id = SnowIdUtil.nextId();
String batchId = data.getJSONObject("res").getString("batchId");
String batchId;
if (isBatch) {
batchId = "toMultiPush";
} else {
batchId = data.getJSONObject("res").getString("batchId");
}
PushLogEntity pushLog = getPushLog(id, informForm, batchId, data.toString(), 2); PushLogEntity pushLog = getPushLog(id, informForm, batchId, data.toString(), 2);
this.save(pushLog); this.save(pushLog);
} catch (Exception e) { } catch (Exception e) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment