短信代码提交

This commit is contained in:
方亮 2026-01-27 09:27:45 +08:00
parent ae71dde47f
commit b16dea93e4
15 changed files with 1093 additions and 5 deletions

View File

@ -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("系统异常,请联系管理员");
}
}
}

View File

@ -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;
}

View File

@ -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()

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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("更新失败");
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}
}

View File

@ -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;
}

View File

@ -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>

View File

@ -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>

View File

@ -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>