|
@@ -1,19 +1,25 @@
|
|
package com.nokia.dingtalk_auto.service;
|
|
package com.nokia.dingtalk_auto.service;
|
|
|
|
|
|
import java.io.File;
|
|
import java.io.File;
|
|
|
|
+import java.text.DateFormat;
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
|
+import java.util.Calendar;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
|
+import org.springframework.scheduling.annotation.Scheduled;
|
|
|
|
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import com.nokia.common.dingtalk.DingtalkUtil;
|
|
import com.nokia.common.dingtalk.DingtalkUtil;
|
|
import com.nokia.common.ssh.SftpUtil;
|
|
import com.nokia.common.ssh.SftpUtil;
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 发送零流量低流量明细
|
|
|
|
|
|
+ * 零流量低流量明细发送
|
|
*/
|
|
*/
|
|
@Service
|
|
@Service
|
|
public class ZeroTrafficTaskService {
|
|
public class ZeroTrafficTaskService {
|
|
@@ -46,43 +52,140 @@ public class ZeroTrafficTaskService {
|
|
@Autowired
|
|
@Autowired
|
|
private MessageService messageService;
|
|
private MessageService messageService;
|
|
|
|
|
|
- public void runTask(String month) {
|
|
|
|
- try {
|
|
|
|
|
|
+ @Autowired
|
|
|
|
+ private ThreadPoolTaskScheduler taskScheduler;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 定时任务,每个月2号早上8点半执行
|
|
|
|
+ */
|
|
|
|
+ @Scheduled(cron = "0 30 8 2 * *")
|
|
|
|
+ public void cronTask() {
|
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
|
+ calendar.add(Calendar.MONTH, -1);
|
|
|
|
+ DateFormat format = new SimpleDateFormat("yyyy-MM");
|
|
|
|
+ String month = format.format(calendar.getTime());
|
|
|
|
+ // 每30分钟检查一次
|
|
|
|
+ checkRemoteDirAndWaitForFileOk(month, 1000L * 60 * 30).thenRun(() -> {
|
|
|
|
+ // 检查完成后下载
|
|
download(month);
|
|
download(month);
|
|
- } catch (Exception e) {
|
|
|
|
- String msg = e.getMessage();
|
|
|
|
- if (msg.endsWith("No such file")) {
|
|
|
|
- // 文件不存在
|
|
|
|
- messageService.error("123456");
|
|
|
|
|
|
+ }).thenRun(() -> {
|
|
|
|
+ // 下载完成后发送
|
|
|
|
+ sendFiles(month);
|
|
|
|
+ }).exceptionally(ex -> {
|
|
|
|
+ // 处理异常--发送提醒并重新抛出异常
|
|
|
|
+ messageService.error(ex.getMessage());
|
|
|
|
+ throw new RuntimeException(ex.getMessage());
|
|
|
|
+ }).join();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 手动执行任务
|
|
|
|
+ *
|
|
|
|
+ * @param month
|
|
|
|
+ */
|
|
|
|
+ public void runTaskManually(String month) {
|
|
|
|
+ CompletableFuture.runAsync(() -> {
|
|
|
|
+ download(month);
|
|
|
|
+ }, taskScheduler).thenRunAsync(() -> {
|
|
|
|
+ sendFiles(month);
|
|
|
|
+ }).exceptionally(ex -> {
|
|
|
|
+ // 处理异常--发送提醒并重新抛出异常
|
|
|
|
+ messageService.error(ex.getMessage());
|
|
|
|
+ throw new RuntimeException(ex.getMessage());
|
|
|
|
+ }).join();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 撤回消息
|
|
|
|
+ *
|
|
|
|
+ * @param messageId
|
|
|
|
+ */
|
|
|
|
+ public void recallMessage(String messageId) {
|
|
|
|
+ dingtalkUtil.recallMessage(openConversationId, messageId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 检查文件是否存在,如果不存在等待milliseconds毫秒后重新检查,直到文件已存在
|
|
|
|
+ *
|
|
|
|
+ * @param month
|
|
|
|
+ * @param milliseconds 毫秒数
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private CompletableFuture<Void> checkRemoteDirAndWaitForFileOk(String month, Long milliseconds) {
|
|
|
|
+ return CompletableFuture.runAsync(() -> {
|
|
|
|
+ checkRemoteDir(month);
|
|
|
|
+ }, taskScheduler).handle((result, ex) -> {
|
|
|
|
+ if (ex != null) {
|
|
|
|
+ String msg = ex.getMessage();
|
|
|
|
+ // 发现文件不存在
|
|
|
|
+ if (msg.endsWith("No such file")) {
|
|
|
|
+ // 发送提醒
|
|
|
|
+ messageService.error("零流量低流量明细账期 " + month + " 文件未具备,请提醒生产方进行生产。");
|
|
|
|
+ // 等待一段时间
|
|
|
|
+ sleep(milliseconds);
|
|
|
|
+ // 重新检查
|
|
|
|
+ return checkRemoteDirAndWaitForFileOk(month, milliseconds).join();
|
|
|
|
+ }
|
|
|
|
+ // 其他异常不进行重试
|
|
|
|
+ messageService.error("零流量低流量明细检查 " + month + " 账期文件时发生异常:" + msg);
|
|
|
|
+ // 重新抛出异常
|
|
|
|
+ throw new RuntimeException(ex.getMessage());
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+ // 没有异常时直接返回结果
|
|
|
|
+ return result;
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 发送文件
|
|
|
|
|
|
+ * 发送文件,两个文件,包括一个截图和一个excel
|
|
*
|
|
*
|
|
* @param month 2023-06 样式的表示月份的字符串
|
|
* @param month 2023-06 样式的表示月份的字符串
|
|
*/
|
|
*/
|
|
- public void sendFiles(String month) {
|
|
|
|
|
|
+ private void sendFiles(String month) {
|
|
String localPath = localDir + month;
|
|
String localPath = localDir + month;
|
|
File[] files = new File(localPath).listFiles();
|
|
File[] files = new File(localPath).listFiles();
|
|
List<String> messageIds = new ArrayList<>();
|
|
List<String> messageIds = new ArrayList<>();
|
|
- // 根据发送文件的后缀发送文件,保证发送顺序
|
|
|
|
|
|
+ // 文件是否存在的标识
|
|
|
|
+ boolean[] flags = new boolean[2];
|
|
|
|
+ // 检查文件是否存在
|
|
for (File file : files) {
|
|
for (File file : files) {
|
|
if (file.getName().toLowerCase().endsWith("1.png")) {
|
|
if (file.getName().toLowerCase().endsWith("1.png")) {
|
|
- String mediaId = dingtalkUtil.upload(file.getAbsolutePath(), "image");
|
|
|
|
- String messageId = dingtalkUtil.sendImage(openConversationId, mediaId);
|
|
|
|
- messageIds.add(messageId);
|
|
|
|
|
|
+ flags[0] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (File file : files) {
|
|
for (File file : files) {
|
|
if (file.getName().toLowerCase().endsWith(month + ".xlsx")) {
|
|
if (file.getName().toLowerCase().endsWith(month + ".xlsx")) {
|
|
- String mediaId = dingtalkUtil.upload(file.getAbsolutePath(), "file");
|
|
|
|
- String messageId = dingtalkUtil.SendFile(openConversationId, mediaId, file.getName());
|
|
|
|
- messageIds.add(messageId);
|
|
|
|
|
|
+ flags[1] = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (flags[0] && flags[1]) {
|
|
|
|
+ // 两个文件都存在才进行发送
|
|
|
|
+ // 根据发送文件的后缀发送文件,保证发送顺序
|
|
|
|
+ for (File file : files) {
|
|
|
|
+ if (file.getName().toLowerCase().endsWith("1.png")) {
|
|
|
|
+ String mediaId = dingtalkUtil.upload(file.getAbsolutePath(), "image");
|
|
|
|
+ String messageId = dingtalkUtil.sendImage(openConversationId, mediaId);
|
|
|
|
+ messageIds.add(messageId);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ for (File file : files) {
|
|
|
|
+ if (file.getName().toLowerCase().endsWith(month + ".xlsx")) {
|
|
|
|
+ String mediaId = dingtalkUtil.upload(file.getAbsolutePath(), "file");
|
|
|
|
+ String messageId = dingtalkUtil.SendFile(openConversationId, mediaId, file.getName());
|
|
|
|
+ messageIds.add(messageId);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ messageService.message(String.format("零流量低流量 %s 账期 完成发送 ==消息id: %s", month, messageIds));
|
|
|
|
+ } else {
|
|
|
|
+ // 如果缺少文件,抛出异常
|
|
|
|
+ StringBuilder stringBuilder = new StringBuilder("零流量低流量 ").append(month).append(" 账期缺少文件:");
|
|
|
|
+ if (!flags[0]) {
|
|
|
|
+ stringBuilder.append("==截图文件==");
|
|
|
|
+ } else if (!flags[1]) {
|
|
|
|
+ stringBuilder.append("==excel文件==");
|
|
|
|
+ }
|
|
|
|
+ throw new RuntimeException(stringBuilder.toString());
|
|
}
|
|
}
|
|
- messageService.message(String.format("零流量低流量 %s 账期 完成发送 ==消息id: %s", month, messageIds));
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -90,22 +193,15 @@ public class ZeroTrafficTaskService {
|
|
*
|
|
*
|
|
* @param month 2023-06 样式的表示月份的字符串
|
|
* @param month 2023-06 样式的表示月份的字符串
|
|
*/
|
|
*/
|
|
- public void download(String month) {
|
|
|
|
|
|
+ private void download(String month) {
|
|
// 创建SftpUtil
|
|
// 创建SftpUtil
|
|
- SftpUtil sftpUtil = new SftpUtil()
|
|
|
|
- .setHost(remoteHost)
|
|
|
|
- .setPort(remotePort)
|
|
|
|
- .setUser(remoteUser)
|
|
|
|
- .setPassword(remotePassword);
|
|
|
|
-
|
|
|
|
|
|
+ SftpUtil sftpUtil = getSftpUtil();
|
|
String remotePath = remoteDir + month;
|
|
String remotePath = remoteDir + month;
|
|
String localPath = localDir + month;
|
|
String localPath = localDir + month;
|
|
-
|
|
|
|
File localFile = new File(localPath);
|
|
File localFile = new File(localPath);
|
|
if (!localFile.exists()) {
|
|
if (!localFile.exists()) {
|
|
localFile.mkdirs();
|
|
localFile.mkdirs();
|
|
}
|
|
}
|
|
-
|
|
|
|
try {
|
|
try {
|
|
// 连接到sftp服务器
|
|
// 连接到sftp服务器
|
|
sftpUtil.connect();
|
|
sftpUtil.connect();
|
|
@@ -121,42 +217,54 @@ public class ZeroTrafficTaskService {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 手动下载文件
|
|
|
|
|
|
+ * 等待一段时间
|
|
*
|
|
*
|
|
- * @param month 2023-06 样式的表示月份的字符串
|
|
|
|
|
|
+ * @param milliseconds 等待的毫秒数
|
|
|
|
+ * @return
|
|
*/
|
|
*/
|
|
- public void downloadManually(String month) {
|
|
|
|
- SftpUtil sftpUtil = new SftpUtil()
|
|
|
|
- .setHost(remoteHost)
|
|
|
|
- .setPort(remotePort)
|
|
|
|
- .setUser(remoteUser)
|
|
|
|
- .setPassword(remotePassword);
|
|
|
|
- String remotePath = remoteDir + month;
|
|
|
|
- String localPath = localDir + month;
|
|
|
|
-
|
|
|
|
- File localFile = new File(localPath);
|
|
|
|
-
|
|
|
|
- if (!localFile.exists()) {
|
|
|
|
- localFile.mkdirs();
|
|
|
|
|
|
+ private void sleep(Long milliseconds) {
|
|
|
|
+ try {
|
|
|
|
+ Thread.sleep(milliseconds);
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
+ e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * 检查文件是否存在
|
|
|
|
+ *
|
|
|
|
+ * @param month
|
|
|
|
+ * @return
|
|
|
|
+ * @throws Exception
|
|
|
|
+ */
|
|
|
|
+ private void checkRemoteDir(String month) {
|
|
|
|
+ SftpUtil sftpUtil = getSftpUtil();
|
|
|
|
+ String remotePath = remoteDir + month;
|
|
try {
|
|
try {
|
|
-
|
|
|
|
|
|
+ // 连接到sftp服务器
|
|
sftpUtil.connect();
|
|
sftpUtil.connect();
|
|
|
|
+ // ls如果路径不存在会触发RuntimeException,携带消息No such file
|
|
List<String> files = sftpUtil.ls(remotePath);
|
|
List<String> files = sftpUtil.ls(remotePath);
|
|
- for (String fileName : files) {
|
|
|
|
- sftpUtil.get(remotePath + "/" + fileName, localPath + "/" + fileName);
|
|
|
|
|
|
+ if (files.size() == 0) {
|
|
|
|
+ // 如果路径存在,但路径下没有文件,抛出RuntimeException,携带消息No such file
|
|
|
|
+ throw new RuntimeException("No such file");
|
|
}
|
|
}
|
|
- } catch (Exception e) {
|
|
|
|
- // 下载失败
|
|
|
|
- e.printStackTrace();
|
|
|
|
} finally {
|
|
} finally {
|
|
- // 从sftp服务器断开连接
|
|
|
|
sftpUtil.disconnect();
|
|
sftpUtil.disconnect();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public void recallMessage(String messageId) {
|
|
|
|
- dingtalkUtil.recallMessage(openConversationId, messageId);
|
|
|
|
|
|
+ /**
|
|
|
|
+ * 获取Sftp连接工具SftpUtil
|
|
|
|
+ *
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private SftpUtil getSftpUtil() {
|
|
|
|
+ // 创建SftpUtil
|
|
|
|
+ return new SftpUtil()
|
|
|
|
+ .setHost(remoteHost)
|
|
|
|
+ .setPort(remotePort)
|
|
|
|
+ .setUser(remoteUser)
|
|
|
|
+ .setPassword(remotePassword);
|
|
}
|
|
}
|
|
}
|
|
}
|