短信代码提交
This commit is contained in:
parent
ae71dde47f
commit
b16dea93e4
|
|
@ -0,0 +1,207 @@
|
|||
package com.bonus.job.controller;
|
||||
|
||||
import com.bonus.common.annotation.Log;
|
||||
import com.bonus.common.core.controller.BaseController;
|
||||
import com.bonus.common.core.domain.AjaxResult;
|
||||
import com.bonus.common.core.domain.entity.SysDept;
|
||||
import com.bonus.common.core.domain.entity.SysRole;
|
||||
import com.bonus.common.core.domain.entity.SysUser;
|
||||
import com.bonus.common.core.page.TableDataInfo;
|
||||
import com.bonus.common.enums.BusinessType;
|
||||
import com.bonus.common.utils.SecurityUtils;
|
||||
import com.bonus.common.utils.StringUtils;
|
||||
import com.bonus.common.utils.poi.ExcelUtil;
|
||||
import com.bonus.job.domain.PmTask;
|
||||
import com.bonus.job.service.PmTaskService;
|
||||
import com.bonus.message.dao.WorkerVo;
|
||||
import com.bonus.system.service.ISysDeptService;
|
||||
import com.bonus.system.service.ISysPostService;
|
||||
import com.bonus.system.service.ISysRoleService;
|
||||
import com.bonus.system.service.ISysUserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 短信任务管理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/msgJob")
|
||||
@Slf4j
|
||||
public class PmTaskController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private PmTaskService service;
|
||||
|
||||
/**
|
||||
* 获取短信任务列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:msgJob:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(PmTask task)
|
||||
{
|
||||
try {
|
||||
startPage();
|
||||
List<PmTask> list = service.getMsgTaskList(task);
|
||||
return getDataTable(list);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return getDataTable(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增短信任务
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:msgJob:add')")
|
||||
@Log(title = "新增短信任务", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
public AjaxResult add(@Validated @RequestBody PmTask task)
|
||||
{
|
||||
try {
|
||||
List<PmTask> msgTaskList = service.getMsgTaskList(task);
|
||||
if (!msgTaskList.isEmpty()) {
|
||||
return AjaxResult.error("任务已存在");
|
||||
}
|
||||
return service.insert(task);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return AjaxResult.error("系统异常,请联系管理员");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个数据详情
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:msgJob:one')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.DELETE)
|
||||
@PostMapping("/getById")
|
||||
public AjaxResult getById(@Validated @RequestBody PmTask task)
|
||||
{
|
||||
try {
|
||||
PmTask data = service.getById(task);
|
||||
return AjaxResult.success(data);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return AjaxResult.error("系统异常,请联系管理员");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改短信任务
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:msgJob:edit')")
|
||||
@Log(title = "修改短信任务", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/update")
|
||||
public AjaxResult edit(@Validated @RequestBody PmTask task)
|
||||
{
|
||||
try {
|
||||
PmTask data = service.getById(task);
|
||||
if(data == null){
|
||||
return AjaxResult.error("任务不存在,无法修改");
|
||||
}
|
||||
if(!task.getTaskName().equals(data.getTaskName())){
|
||||
List<PmTask> msgTaskList = service.getMsgTaskList(task);
|
||||
if (!msgTaskList.isEmpty()) {
|
||||
return AjaxResult.error("任务已存在");
|
||||
}
|
||||
}
|
||||
return service.update(task);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return AjaxResult.error("系统异常,请联系管理员");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除短信任务
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:msgJob:remove')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.DELETE)
|
||||
@PostMapping("delete")
|
||||
public AjaxResult delete(@Validated @RequestBody PmTask task)
|
||||
{
|
||||
try {
|
||||
return service.delete(task);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return AjaxResult.error("系统异常,请联系管理员");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 短信平台回执
|
||||
*/
|
||||
@Log(title = "短信平台回执", businessType = BusinessType.DELETE)
|
||||
@PostMapping("msgSendStatus")
|
||||
public AjaxResult msgSendStatus(String msg)
|
||||
{
|
||||
try {
|
||||
return service.msgSendStatus(msg);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return AjaxResult.error("数据格式异常");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询短信循环次数
|
||||
*/
|
||||
@Log(title = "查询短信循环数据", businessType = BusinessType.OTHER)
|
||||
@PostMapping("getMsgLoopData")
|
||||
public TableDataInfo getMsgLoopData(@Validated @RequestBody PmTask o)
|
||||
{
|
||||
try {
|
||||
startPage();
|
||||
List<PmTask> list= service.getMsgLoopData(o);
|
||||
return getDataTable(list);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return getDataTable(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询短信循环次数
|
||||
*/
|
||||
@Log(title = "查询单次短信循环详细数据", businessType = BusinessType.OTHER)
|
||||
@PostMapping("getOneLoopMsgData")
|
||||
public AjaxResult getOneLoopMsgData(@Validated @RequestBody PmTask o)
|
||||
{
|
||||
try {
|
||||
return service.getOneLoopMsgData(o);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return AjaxResult.error("系统异常,请联系管理员");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动重新发送
|
||||
*/
|
||||
@Log(title = "单人重新发送", businessType = BusinessType.OTHER)
|
||||
@PostMapping("oneWorkerResend")
|
||||
public AjaxResult oneWorkerResend(@Validated @RequestBody WorkerVo o)
|
||||
{
|
||||
try {
|
||||
return service.oneWorkerResend(o);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return AjaxResult.error("系统异常,请联系管理员");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.bonus.job.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.bonus.message.dao.WorkerVo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PmTask {
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 任务要求(任务中文描述)
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 1 通知 2计划
|
||||
*/
|
||||
private Integer msgType;
|
||||
|
||||
/**
|
||||
* 发送内容
|
||||
*/
|
||||
private String sendContent;
|
||||
|
||||
/**
|
||||
* 任务状态 (0正常 1暂停)
|
||||
*/
|
||||
private Integer taskStatus;
|
||||
|
||||
/**
|
||||
* 人员数量
|
||||
*/
|
||||
private String workerCount;
|
||||
|
||||
/**
|
||||
* 人员列表
|
||||
*/
|
||||
private List<WorkerVo> workerList;
|
||||
|
||||
private String loopTime;
|
||||
|
||||
private Long loopId;
|
||||
|
||||
/**
|
||||
* 并发执行
|
||||
*/
|
||||
private String concurrent;
|
||||
|
||||
/**
|
||||
* 调度周期
|
||||
*/
|
||||
private String cronExpression;
|
||||
|
||||
/**
|
||||
* 错失执行策略
|
||||
*/
|
||||
private String misfirePolicy;
|
||||
|
||||
}
|
||||
|
|
@ -57,6 +57,12 @@ public class SysJob extends BaseEntity
|
|||
@Excel(name = "任务状态", readConverterExp = "0=正常,1=暂停")
|
||||
private String status;
|
||||
|
||||
/** 关联id */
|
||||
private Integer relationId;
|
||||
|
||||
/** 关联id */
|
||||
private String relationType;
|
||||
|
||||
@NotBlank(message = "任务名称不能为空")
|
||||
@Size(min = 0, max = 64, message = "任务名称不能超过64个字符")
|
||||
public String getJobName()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package com.bonus.job.mapper;
|
||||
|
||||
import com.bonus.common.core.domain.AjaxResult;
|
||||
import com.bonus.job.domain.PmTask;
|
||||
import com.bonus.message.dao.WorkerVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PmTaskMapper {
|
||||
|
||||
int insert(PmTask record);
|
||||
|
||||
List<PmTask> getMsgTaskList(PmTask task);
|
||||
|
||||
PmTask getById(PmTask task);
|
||||
|
||||
int update(PmTask task);
|
||||
|
||||
int delete(PmTask task);
|
||||
|
||||
/**
|
||||
* 获取任务下的所有执行者
|
||||
* @return
|
||||
*/
|
||||
List<WorkerVo> getWorkerByTaskId(Integer taskId);
|
||||
|
||||
void insertTaskWorker(@Param("list") List<WorkerVo> workerList);
|
||||
|
||||
void delTaskWorker(PmTask task);
|
||||
|
||||
int msgSendStatus(@Param("list") List<WorkerVo> list);
|
||||
|
||||
List<PmTask> getMsgLoopData(PmTask o);
|
||||
|
||||
PmTask getOneLoopMsgData(PmTask o);
|
||||
|
||||
List<WorkerVo> getWorkerRecordByLoopId(Long loopId);
|
||||
|
||||
int updateOneWorkerData(WorkerVo o);
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.bonus.job.mapper;
|
||||
|
||||
import com.bonus.job.domain.*;
|
||||
import com.bonus.message.dao.WorkerVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -12,4 +13,18 @@ import java.util.List;
|
|||
*/
|
||||
public interface WorkerJobMapper {
|
||||
|
||||
/**
|
||||
* 通过调度ID查询调度任务信息
|
||||
*
|
||||
* @param jobId 调度ID
|
||||
* @return 角色对象信息
|
||||
*/
|
||||
List<WorkerVo> getWorkerByJobId(String jobId);
|
||||
|
||||
/**
|
||||
* 批量插入任务记录
|
||||
*
|
||||
* @param userList
|
||||
*/
|
||||
void insertTaskRecord(List<WorkerVo> userList);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package com.bonus.job.service;
|
||||
|
||||
import com.bonus.common.core.domain.AjaxResult;
|
||||
import com.bonus.job.domain.PmTask;
|
||||
import com.bonus.message.dao.WorkerVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PmTaskService{
|
||||
|
||||
List<PmTask> getMsgTaskList(PmTask task);
|
||||
|
||||
AjaxResult insert(PmTask task);
|
||||
|
||||
PmTask getById(PmTask task);
|
||||
|
||||
AjaxResult update(PmTask task);
|
||||
|
||||
AjaxResult delete(PmTask task);
|
||||
|
||||
AjaxResult msgSendStatus(String msg);
|
||||
|
||||
List<PmTask> getMsgLoopData(PmTask o);
|
||||
|
||||
AjaxResult getOneLoopMsgData(PmTask o);
|
||||
|
||||
AjaxResult oneWorkerResend(WorkerVo o);
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
package com.bonus.job.service;
|
||||
|
||||
import com.bonus.common.core.domain.AjaxResult;
|
||||
import com.bonus.job.util.MessageSendUtil;
|
||||
import com.bonus.message.dao.WorkerVo;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.bonus.job.mapper.PmTaskMapper;
|
||||
import com.bonus.job.domain.PmTask;
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PmTaskServiceImpl implements PmTaskService{
|
||||
|
||||
@Resource
|
||||
private PmTaskMapper mapper;
|
||||
|
||||
@Override
|
||||
public List<PmTask> getMsgTaskList(PmTask task) {
|
||||
return mapper.getMsgTaskList(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult insert(PmTask task) {
|
||||
int insert = mapper.insert(task);
|
||||
if(insert > 0){
|
||||
task.getWorkerList().forEach(worker -> worker.setTaskId(task.getId()));
|
||||
mapper.insertTaskWorker(task.getWorkerList());
|
||||
}
|
||||
return insert > 0 ? AjaxResult.success("添加成功",task) : AjaxResult.error("添加失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PmTask getById(PmTask task) {
|
||||
PmTask byId = mapper.getById(task);
|
||||
if(byId != null && byId.getId() != null){
|
||||
List<WorkerVo> list = mapper.getWorkerByTaskId(task.getId());
|
||||
byId.setWorkerList(list);
|
||||
}
|
||||
return byId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult update(PmTask task) {
|
||||
int update = mapper.update(task);
|
||||
if(update > 0){
|
||||
task.getWorkerList().forEach(worker -> worker.setTaskId(task.getId()));
|
||||
mapper.delTaskWorker(task);
|
||||
mapper.insertTaskWorker(task.getWorkerList());
|
||||
}
|
||||
return update > 0 ? AjaxResult.success("修改成功",task) : AjaxResult.error("修改失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult delete(PmTask task) {
|
||||
int delete = mapper.delete(task);
|
||||
return delete > 0 ? AjaxResult.success("删除成功",task) : AjaxResult.error("删除失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult msgSendStatus(String msg) {
|
||||
if (msg == null) {
|
||||
return AjaxResult.error("参数错误");
|
||||
}
|
||||
String[] split = msg.split(";");
|
||||
List<WorkerVo> list = new ArrayList<>();
|
||||
for (String s : split) {
|
||||
String[] splitStatus = s.split(",");
|
||||
if (splitStatus.length >=3) {
|
||||
WorkerVo bean = new WorkerVo();
|
||||
bean.setBatchNumber(splitStatus[0]);
|
||||
bean.setPhone(splitStatus[1]);
|
||||
if("1".equals(splitStatus[2])){
|
||||
bean.setSendStatus("发送成功");
|
||||
}else{
|
||||
bean.setReason("发送失败");
|
||||
}
|
||||
list.add(bean);
|
||||
}
|
||||
}
|
||||
int i = mapper.msgSendStatus(list);
|
||||
return i > 0 ? AjaxResult.success("更新成功") : AjaxResult.error("更新失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PmTask> getMsgLoopData(PmTask o) {
|
||||
return mapper.getMsgLoopData(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult getOneLoopMsgData(PmTask o) {
|
||||
PmTask oneLoopMsgData = mapper.getOneLoopMsgData(o);
|
||||
List<WorkerVo> list = mapper.getWorkerRecordByLoopId(oneLoopMsgData.getLoopId());
|
||||
oneLoopMsgData.setWorkerList(list);
|
||||
return AjaxResult.success(oneLoopMsgData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult oneWorkerResend(WorkerVo o) {
|
||||
//1.先去查短信内容
|
||||
List<WorkerVo> userList = new ArrayList<>();
|
||||
userList.add(o);
|
||||
MessageSendUtil messageSendUtil = new MessageSendUtil();
|
||||
String msgResult = messageSendUtil.sendMessage(userList, o.getSendContent());
|
||||
if (msgResult == null){
|
||||
return AjaxResult.error("短信发送返回异常:"+msgResult);
|
||||
}
|
||||
String[] split = msgResult.split(",");
|
||||
if (split.length == 2 && "ok".equals(split[0])) {
|
||||
// 发送成功,更新任务状态为成功
|
||||
o.setSubmitStatus(split[0]);
|
||||
o.setBatchNumber(split[1]);
|
||||
} else {
|
||||
// 发送失败,更新任务状态为失败
|
||||
o.setSubmitStatus(split[0]);
|
||||
o.setReason(split[1]);
|
||||
}
|
||||
// 在设置发送时间时使用时分秒格式
|
||||
LocalTime currentTime = LocalTime.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||
o.setSendTime(currentTime.format(formatter));
|
||||
int i = mapper.updateOneWorkerData(o);
|
||||
return i > 0 ? AjaxResult.success("更新成功") : AjaxResult.error("更新失败");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,11 +1,21 @@
|
|||
package com.bonus.job.task;
|
||||
|
||||
import com.bonus.job.mapper.WorkerJobMapper;
|
||||
import com.bonus.job.util.HttpRequestHelper;
|
||||
import com.bonus.job.util.MessageSendUtil;
|
||||
import com.bonus.job.util.SnowflakeIdGenerator;
|
||||
import com.bonus.message.dao.WorkerVo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 定时任务调度测试
|
||||
|
|
@ -20,16 +30,80 @@ public class WorkerSendMsgTask{
|
|||
@Resource
|
||||
private WorkerJobMapper mapper;
|
||||
|
||||
/**
|
||||
* 人员短信调度
|
||||
*/
|
||||
public void updateEinDayRecord(){
|
||||
try{
|
||||
SnowflakeIdGenerator idGen = new SnowflakeIdGenerator(1, 1);
|
||||
|
||||
/**
|
||||
* 人员短信调度执行
|
||||
*/
|
||||
public void sendMsg(String jobId){
|
||||
try{
|
||||
//查询任务发送人人员信息
|
||||
List<WorkerVo> list = mapper.getWorkerByJobId(jobId);
|
||||
sendInBatches(list);
|
||||
}catch (Exception e){
|
||||
logger.error("人员短信调度,{}",e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 批量发送短信
|
||||
*/
|
||||
public void sendInBatches(List<WorkerVo> workers) {
|
||||
String content = workers.get(0).getSendContent();
|
||||
long loopId = idGen.nextId();
|
||||
final int BATCH_SIZE = 200;
|
||||
if (workers.size() <= BATCH_SIZE) {
|
||||
// 不超过200人,单次发送
|
||||
msgFlow(workers, content, loopId);
|
||||
} else {
|
||||
// 超过200人,分批次发送
|
||||
for (int i = 0; i < workers.size(); i += BATCH_SIZE) {
|
||||
int end = Math.min(i + BATCH_SIZE, workers.size());
|
||||
List<WorkerVo> batch = workers.subList(i, end);
|
||||
msgFlow(batch, content, loopId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信发送
|
||||
*/
|
||||
private String msgFlow(List<WorkerVo> userList, String content, long loopId) {
|
||||
//1.发送短信
|
||||
MessageSendUtil messageSendUtil = new MessageSendUtil();
|
||||
String msgResult = messageSendUtil.sendMessage(userList, content);
|
||||
String[] split = msgResult.split(",");
|
||||
if (split.length == 2 && "ok".equals(split[0])) {
|
||||
// 批量发送成功,更新任务状态为成功
|
||||
userList.forEach(user -> {
|
||||
user.setLoopId(loopId);
|
||||
user.setPhone(user.getPhone());
|
||||
user.setSubmitStatus(split[0]);
|
||||
user.setBatchNumber(split[1]);
|
||||
// 在设置发送时间时使用时分秒格式
|
||||
LocalTime currentTime = LocalTime.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||
user.setSendTime(currentTime.format(formatter));
|
||||
});
|
||||
|
||||
} else {
|
||||
// 批量发送失败,更新任务状态为失败
|
||||
userList.forEach(user -> {
|
||||
user.setLoopId(loopId);
|
||||
user.setPhone(user.getPhone());
|
||||
user.setSubmitStatus(split[0]);
|
||||
user.setReason(split[1]);
|
||||
// 在设置发送时间时使用时分秒格式
|
||||
LocalTime currentTime = LocalTime.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||
user.setSendTime(currentTime.format(formatter));
|
||||
});
|
||||
}
|
||||
mapper.insertTaskRecord(userList);
|
||||
return msgResult;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,128 @@
|
|||
package com.bonus.job.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class HttpRequestHelper {
|
||||
public HttpRequestHelper() {
|
||||
}
|
||||
|
||||
public static String doGet(String httpUrl) {
|
||||
HttpURLConnection connection = null;
|
||||
InputStream is = null;
|
||||
BufferedReader br = null;
|
||||
StringBuffer result = new StringBuffer();
|
||||
|
||||
try {
|
||||
URL url = new URL(httpUrl);
|
||||
connection = (HttpURLConnection)url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(15000);
|
||||
connection.setReadTimeout(15000);
|
||||
connection.connect();
|
||||
if (connection.getResponseCode() == 200) {
|
||||
is = connection.getInputStream();
|
||||
if (is != null) {
|
||||
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
|
||||
String temp = null;
|
||||
|
||||
while((temp = br.readLine()) != null) {
|
||||
result.append(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (MalformedURLException var22) {
|
||||
var22.printStackTrace();
|
||||
} catch (IOException var23) {
|
||||
var23.printStackTrace();
|
||||
} finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException var21) {
|
||||
var21.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException var20) {
|
||||
var20.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String doPost(String httpUrl, String param) {
|
||||
StringBuffer result = new StringBuffer();
|
||||
HttpURLConnection connection = null;
|
||||
OutputStream os = null;
|
||||
InputStream is = null;
|
||||
BufferedReader br = null;
|
||||
|
||||
try {
|
||||
URL url = new URL(httpUrl);
|
||||
connection = (HttpURLConnection)url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setConnectTimeout(15000);
|
||||
connection.setReadTimeout(15000);
|
||||
connection.setDoOutput(true);
|
||||
connection.setDoInput(true);
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
if (param != null && !param.equals("")) {
|
||||
os = connection.getOutputStream();
|
||||
os.write(param.getBytes("UTF-8"));
|
||||
}
|
||||
|
||||
if (connection.getResponseCode() == 200) {
|
||||
is = connection.getInputStream();
|
||||
if (is != null) {
|
||||
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
|
||||
String temp = null;
|
||||
if ((temp = br.readLine()) != null) {
|
||||
result.append(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (MalformedURLException var29) {
|
||||
var29.printStackTrace();
|
||||
} catch (IOException var30) {
|
||||
var30.printStackTrace();
|
||||
} finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException var28) {
|
||||
var28.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (os != null) {
|
||||
try {
|
||||
os.close();
|
||||
} catch (IOException var27) {
|
||||
var27.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException var26) {
|
||||
var26.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package com.bonus.job.util;
|
||||
|
||||
import com.bonus.message.dao.WorkerVo;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MessageSendUtil {
|
||||
|
||||
// API配置常量
|
||||
final String DDTKEY = "bonusyn";
|
||||
final String SECRET_KEY = "IU0ypHbH";
|
||||
final String API_URL = "http://api.ktsms.cn/sms_token";
|
||||
|
||||
// 错误码映射表(根据你提供的文档)
|
||||
private static final Map<String, String> ERROR_CODE_TO_MESSAGE = new HashMap<>();
|
||||
static {
|
||||
ERROR_CODE_TO_MESSAGE.put("1001", "用户名密码错误");
|
||||
ERROR_CODE_TO_MESSAGE.put("1002", "通道配置移除或没有配置通道");
|
||||
ERROR_CODE_TO_MESSAGE.put("1003", "IP验证错误");
|
||||
ERROR_CODE_TO_MESSAGE.put("1004", "签名不规范");
|
||||
ERROR_CODE_TO_MESSAGE.put("1005", "次数超限");
|
||||
ERROR_CODE_TO_MESSAGE.put("1006", "用户余额不足");
|
||||
ERROR_CODE_TO_MESSAGE.put("1007", "扣费异常");
|
||||
ERROR_CODE_TO_MESSAGE.put("1008", "数据接收失败,余额不足");
|
||||
ERROR_CODE_TO_MESSAGE.put("1009", "扣费失败或内容错误");
|
||||
ERROR_CODE_TO_MESSAGE.put("1010", "短信内容为空,或编码不正确引起");
|
||||
ERROR_CODE_TO_MESSAGE.put("1011", "有效号码为空");
|
||||
ERROR_CODE_TO_MESSAGE.put("1012", "接口参数异常,请检查参数名称");
|
||||
ERROR_CODE_TO_MESSAGE.put("1013", "发送内容超过500个字");
|
||||
ERROR_CODE_TO_MESSAGE.put("1014", "发送号码超过200个号码(个性化号码大于200或者小于1)");
|
||||
ERROR_CODE_TO_MESSAGE.put("1015", "用户名密码错误或余额不足,接口屏蔽");
|
||||
ERROR_CODE_TO_MESSAGE.put("1016", "定时参数不正确。格式为:yyyyMMddHHmmss");
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信发送
|
||||
*/
|
||||
/**
|
||||
* 短信发送
|
||||
*/
|
||||
public String sendMessage(List<WorkerVo> userList, String content) {
|
||||
// 构建手机号字符串,用逗号分隔
|
||||
String mobiles = userList.stream()
|
||||
.map(WorkerVo::getPhone)
|
||||
.collect(Collectors.joining(","));
|
||||
// 构建请求URL
|
||||
String url = API_URL + "?ddtkey=" + DDTKEY + "&secretkey=" + SECRET_KEY;
|
||||
String uri = url + "&mobile=" + mobiles + "&content=" + content;
|
||||
// 构建JSON参数
|
||||
String param = String.format(
|
||||
"{\"ddtkey\":\"%s\",\"secretkey\":\"%s\",\"mobile\":\"%s\",\"content\":\"%s\"}",
|
||||
DDTKEY, SECRET_KEY, mobiles, content
|
||||
);
|
||||
return convertToMessage(HttpRequestHelper.doPost(uri, param));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将短信平台返回的错误码转换为中文说明
|
||||
*
|
||||
* @param response 原始响应,如 "error,1001" 或 "ok,MSG123"
|
||||
* @return 转换后的字符串,如 "error,用户名密码错误" 或 "ok,MSG123"
|
||||
*/
|
||||
public static String convertToMessage(String response) {
|
||||
if (response == null || response.isEmpty()) {
|
||||
return response;
|
||||
}
|
||||
// 只处理以 "error," 开头的响应
|
||||
if (response.startsWith("error,")) {
|
||||
String[] parts = response.split(",", 2);
|
||||
if (parts.length == 2) {
|
||||
String code = parts[1].trim();
|
||||
String message = ERROR_CODE_TO_MESSAGE.get(code);
|
||||
if (message != null) {
|
||||
return "error," + message;
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package com.bonus.job.util;
|
||||
|
||||
public class SnowflakeIdGenerator {
|
||||
|
||||
// ================== 基础配置 ==================
|
||||
private final long twepoch = 1704067200000L; // 起始时间戳(2024-01-01 00:00:00 UTC)
|
||||
|
||||
private final long datacenterIdBits = 5L;
|
||||
private final long workerIdBits = 5L;
|
||||
private final long sequenceBits = 12L;
|
||||
|
||||
private final long maxDatacenterId = ~(-1L << datacenterIdBits); // 31
|
||||
private final long maxWorkerId = ~(-1L << workerIdBits); // 31
|
||||
private final long maxSequence = ~(-1L << sequenceBits); // 4095
|
||||
|
||||
private final long workerIdShift = sequenceBits;
|
||||
private final long datacenterIdShift = sequenceBits + workerIdBits;
|
||||
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
|
||||
|
||||
// ================== 实例变量 ==================
|
||||
private final long datacenterId;
|
||||
private final long workerId;
|
||||
private long sequence = 0L;
|
||||
private long lastTimestamp = -1L;
|
||||
|
||||
// ================== 构造函数 ==================
|
||||
public SnowflakeIdGenerator(long datacenterId, long workerId) {
|
||||
if (datacenterId > maxDatacenterId || datacenterId < 0) {
|
||||
throw new IllegalArgumentException("datacenterId 不能大于 " + maxDatacenterId + " 或小于 0");
|
||||
}
|
||||
if (workerId > maxWorkerId || workerId < 0) {
|
||||
throw new IllegalArgumentException("workerId 不能大于 " + maxWorkerId + " 或小于 0");
|
||||
}
|
||||
this.datacenterId = datacenterId;
|
||||
this.workerId = workerId;
|
||||
}
|
||||
|
||||
// ================== 核心方法 ==================
|
||||
public synchronized long nextId() {
|
||||
long timestamp = timeGen();
|
||||
|
||||
// 时钟回拨检查
|
||||
if (timestamp < lastTimestamp) {
|
||||
throw new RuntimeException("时钟回拨,拒绝生成 ID:" + lastTimestamp + " -> " + timestamp);
|
||||
}
|
||||
|
||||
if (lastTimestamp == timestamp) {
|
||||
// 同一毫秒内,序列号自增
|
||||
sequence = (sequence + 1) & maxSequence;
|
||||
if (sequence == 0) {
|
||||
// 序列号用完,等待下一毫秒
|
||||
timestamp = tilNextMillis(lastTimestamp);
|
||||
}
|
||||
} else {
|
||||
// 新的一毫秒,序列号重置
|
||||
sequence = 0L;
|
||||
}
|
||||
|
||||
lastTimestamp = timestamp;
|
||||
|
||||
return ((timestamp - twepoch) << timestampLeftShift)
|
||||
| (datacenterId << datacenterIdShift)
|
||||
| (workerId << workerIdShift)
|
||||
| sequence;
|
||||
}
|
||||
|
||||
// ================== 工具方法 ==================
|
||||
private long tilNextMillis(long lastTimestamp) {
|
||||
long timestamp = timeGen();
|
||||
while (timestamp <= lastTimestamp) {
|
||||
timestamp = timeGen();
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
private long timeGen() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// ================== 测试 ==================
|
||||
public static void main(String[] args) {
|
||||
SnowflakeIdGenerator idGen = new SnowflakeIdGenerator(1, 1);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
System.out.println(idGen.nextId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -67,4 +67,19 @@ public class WorkerVo {
|
|||
*/
|
||||
private int groupId;
|
||||
|
||||
private Integer taskId;
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
private String sendContent;
|
||||
|
||||
//任务记录
|
||||
private String batchNumber;
|
||||
private Long loopId;
|
||||
private String sendTime;
|
||||
private String submitStatus;
|
||||
private String sendStatus;
|
||||
private String reason;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.bonus.job.mapper.PmTaskMapper">
|
||||
<resultMap id="BaseResultMap" type="com.bonus.job.domain.PmTask">
|
||||
<id column="id" jdbcType="INTEGER" property="id" />
|
||||
<result column="task_name" jdbcType="VARCHAR" property="taskName" />
|
||||
<result column="remark" jdbcType="VARCHAR" property="remark" />
|
||||
<result column="msg_type" jdbcType="INTEGER" property="msgType" />
|
||||
<result column="send_content" jdbcType="VARCHAR" property="sendContent" />
|
||||
<result column="task_status" jdbcType="INTEGER" property="taskStatus" />
|
||||
<result column="worker_count" property="workerCount"/>
|
||||
<result column="loopTime" property="loopTime"/>
|
||||
<result column="loop_id" property="loopId"/>
|
||||
<result column="concurrent" property="concurrent"/>
|
||||
<result column="cron_expression" property="cronExpression"/>
|
||||
<result column="misfire_policy" property="misfirePolicy"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.bonus.job.domain.PmTask" useGeneratedKeys="true">
|
||||
insert into pm_task (task_name, remark, msg_type, send_content)
|
||||
values (#{taskName}, #{remark},#{msgType},#{sendContent})
|
||||
</insert>
|
||||
|
||||
<select id="getMsgTaskList" resultMap="BaseResultMap">
|
||||
select
|
||||
pt.id, pt.task_name, pt.remark, pt.msg_type, pt.send_content,
|
||||
sj.status as task_status,count(bm.worker_id) as worker_count
|
||||
from pm_task pt
|
||||
left join sys_job sj on pt.id = sj.relation_id and sj.relation_type = '短信'
|
||||
left join bm_task_worker bm on pt.id = bm.task_id
|
||||
<where>
|
||||
is_active = 1
|
||||
<if test="taskName != null">
|
||||
and task_name like concat('%',#{taskName},'%')
|
||||
</if>
|
||||
<if test="msgType != null">
|
||||
and msg_type = #{msgType}
|
||||
</if>
|
||||
</where>
|
||||
group by pt.id
|
||||
</select>
|
||||
|
||||
<select id="getById" resultMap="BaseResultMap">
|
||||
select
|
||||
pt.id, pt.task_name, pt.remark, pt.msg_type, pt.send_content,
|
||||
sj.status as task_status
|
||||
from pm_task pt
|
||||
left join sys_job sj on pt.id = sj.relation_id and sj.relation_type = '短信'
|
||||
where id = #{id} and is_active = 1
|
||||
</select>
|
||||
|
||||
<update id="update">
|
||||
update pm_task
|
||||
<set>
|
||||
<if test="taskName != null">
|
||||
task_name = #{taskName},
|
||||
</if>
|
||||
<if test="remark != null">
|
||||
remark = #{remark},
|
||||
</if>
|
||||
<if test="msgType != null">
|
||||
msg_type = #{msgType},
|
||||
</if>
|
||||
<if test="sendContent != null">
|
||||
send_content = #{sendContent},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="delete">
|
||||
update pm_task set is_active = 0
|
||||
where id = #{id}
|
||||
</delete>
|
||||
|
||||
<select id="getWorkerByTaskId" resultType="com.bonus.message.dao.WorkerVo">
|
||||
select
|
||||
bm.worker_id as id, w.worker_name
|
||||
from bm_task_worker bm
|
||||
left join pm_worker w on bm.worker_id = w.id
|
||||
where bm.task_id = #{taskId}
|
||||
</select>
|
||||
|
||||
<insert id="insertTaskWorker">
|
||||
insert into bm_task_worker (task_id, worker_id)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.taskId},#{item.id})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<delete id="delTaskWorker">
|
||||
delete from bm_task_worker where task_id = #{id}
|
||||
</delete>
|
||||
|
||||
<update id="msgSendStatus">
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
update bm_task_record set send_status = #{item.sendStatus} where batch_number = #{item.batchNumber} and phone = #{item.phone}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<select id="getMsgLoopData" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
pt.id,
|
||||
btw.loop_id,
|
||||
pt.task_name,
|
||||
pt.remark,
|
||||
pt.msg_type,
|
||||
btw.create_time AS loopTime
|
||||
FROM
|
||||
pm_task pt
|
||||
LEFT JOIN bm_task_record btw ON btw.task_id = pt.id
|
||||
WHERE
|
||||
pt.id = #{id}
|
||||
GROUP BY
|
||||
btw.loop_id
|
||||
</select>
|
||||
|
||||
<select id="getOneLoopMsgData" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
pt.id,
|
||||
pt.task_name,
|
||||
pt.msg_type,
|
||||
pt.send_content,
|
||||
pt.remark,
|
||||
sj.status AS task_status,
|
||||
sj.cron_expression,
|
||||
sj.misfire_policy,
|
||||
sj.concurrent
|
||||
FROM
|
||||
pm_task pt
|
||||
left join sys_job sj on pt.id = sj.relation_id and sj.relation_type = '短信'
|
||||
WHERE
|
||||
pt.id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="getWorkerRecordByLoopId" resultType="com.bonus.message.dao.WorkerVo">
|
||||
|
||||
SELECT
|
||||
btw.id,
|
||||
w.worker_name,
|
||||
btw.phone,
|
||||
btw.send_time,
|
||||
btw.submit_status,
|
||||
btw.reason,
|
||||
btw.send_status
|
||||
FROM
|
||||
bm_task_record btw
|
||||
left join pm_worker w on btw.worker_id = w.id
|
||||
WHERE
|
||||
btw.loop_id = #{loopId}
|
||||
</select>
|
||||
|
||||
<update id="updateOneWorkerData">
|
||||
update bm_task_record set batch_number= #{batchNumber},submit_status = #{submitStatus},reason = #{reason} where id = #{id}
|
||||
</update>
|
||||
</mapper>
|
||||
|
|
@ -91,6 +91,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="status != null and status != ''">status,</if>
|
||||
<if test="remark != null and remark != ''">remark,</if>
|
||||
<if test="createBy != null and createBy != ''">create_by,</if>
|
||||
<if test="relationId != null and relationId != ''">relation_id,</if>
|
||||
<if test="relationType != null and relationType != ''">relation_type,</if>
|
||||
create_time
|
||||
)values(
|
||||
<if test="jobId != null and jobId != 0">#{jobId},</if>
|
||||
|
|
@ -103,6 +105,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="status != null and status != ''">#{status},</if>
|
||||
<if test="remark != null and remark != ''">#{remark},</if>
|
||||
<if test="createBy != null and createBy != ''">#{createBy},</if>
|
||||
<if test="relationId != null and relationId != ''">#{relationId},</if>
|
||||
<if test="relationType != null and relationType != ''">#{relationType},</if>
|
||||
sysdate()
|
||||
)
|
||||
</insert>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.bonus.job.mapper.WorkerJobMapper">
|
||||
<resultMap id="BaseResultMap" type="com.bonus.job.domain.PmTask">
|
||||
<id column="id" jdbcType="INTEGER" property="id" />
|
||||
<result column="task_name" jdbcType="VARCHAR" property="taskName" />
|
||||
<result column="remark" jdbcType="VARCHAR" property="remark" />
|
||||
<result column="msg_type" jdbcType="INTEGER" property="msgType" />
|
||||
<result column="send_content" jdbcType="VARCHAR" property="sendContent" />
|
||||
<result column="task_status" jdbcType="INTEGER" property="taskStatus" />
|
||||
</resultMap>
|
||||
|
||||
<select id="getById" resultMap="BaseResultMap">
|
||||
select
|
||||
pt.id, pt.task_name, pt.remark, pt.msg_type, pt.send_content,
|
||||
sj.status as task_status
|
||||
from pm_task pt
|
||||
left join sys_job sj on pt.id = sj.relation_id and sj.relation_type = '短信'
|
||||
where id = #{id} and is_active = 1
|
||||
</select>
|
||||
|
||||
|
||||
<select id="getWorkerByJobId" resultType="com.bonus.message.dao.WorkerVo">
|
||||
select
|
||||
pt.task_name, pt.send_content, w.worker_name, w.phone
|
||||
from pm_task pt
|
||||
left join bm_task_worker bm on pt.id = bm.task_id
|
||||
left join pm_worker w on bm.worker_id = w.id
|
||||
where pt.id = #{jobId}
|
||||
</select>
|
||||
|
||||
<insert id="insertTaskRecord">
|
||||
insert into bm_task_record (task_id, loop_id, worker_id, phone, batch_number, submit_status, send_time, reason)
|
||||
values
|
||||
<foreach item="item" index="index" collection="list" separator=",">
|
||||
(#{item.taskId}, #{item.loopId}, #{item.id}, #{item.phone}, #{item.batchNumber}, #{item.submitStatus}, #{item.sendTime}, #{item.reason})
|
||||
</foreach>
|
||||
</insert>
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue