feat: 初始化 rkutils 项目
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+29
@@ -24,3 +24,32 @@
|
||||
hs_err_pid*
|
||||
replay_pid*
|
||||
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
*.log
|
||||
*.flattened-pom.xml
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
||||
|
||||
### Mac files ###
|
||||
*.DS_Store
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-parent</artifactId>
|
||||
<version>3.9.0</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
|
||||
<groupId>com.renkang</groupId>
|
||||
<artifactId>rkutils</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<description>rkutils project for Solon</description>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-lib</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-scheduling-simple</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-logging-logback-jakarta</artifactId>
|
||||
</dependency>
|
||||
<!-- Source: https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
<version>2.0.60</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-net-httputils</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>tencent</id>
|
||||
<url>https://mirrors.cloud.tencent.com/nexus/repository/maven-public/</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.renkang.rkutils;
|
||||
|
||||
import com.renkang.rkutils.service.LogFileService;
|
||||
import org.noear.solon.Solon;
|
||||
import org.noear.solon.annotation.SolonMain;
|
||||
import org.noear.solon.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@EnableScheduling
|
||||
@SolonMain
|
||||
public class App {
|
||||
public static void main(String[] args) {
|
||||
Solon.start(App.class, args);
|
||||
LogFileService logFileService = Solon.context().getBean(LogFileService.class);
|
||||
logFileService.downloadLogFile();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.renkang.rkutils.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.noear.solon.annotation.Configuration;
|
||||
import org.noear.solon.annotation.Inject;
|
||||
|
||||
@Configuration
|
||||
@Inject("${base}")
|
||||
@Data
|
||||
public class BaseConfig {
|
||||
private String username;
|
||||
private String password;
|
||||
private String gatewayUrl;
|
||||
private String publicKey;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.renkang.rkutils.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.noear.solon.annotation.Configuration;
|
||||
import org.noear.solon.annotation.Inject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@Inject("${file}")
|
||||
@Data
|
||||
public class LogFileConfig {
|
||||
private String path;
|
||||
private List<ServiceItem> services;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class ServiceItem {
|
||||
private String name;
|
||||
private int insCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.renkang.rkutils.service;
|
||||
|
||||
public interface LogFileService {
|
||||
public void downloadLogFile();
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
package com.renkang.rkutils.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.renkang.rkutils.config.BaseConfig;
|
||||
import com.renkang.rkutils.config.LogFileConfig;
|
||||
import com.renkang.rkutils.service.LogFileService;
|
||||
import com.renkang.rkutils.vo.FileInfo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.noear.solon.annotation.Component;
|
||||
import org.noear.solon.annotation.Inject;
|
||||
import org.noear.solon.core.util.DateUtil;
|
||||
import org.noear.solon.net.http.HttpResponse;
|
||||
import org.noear.solon.net.http.HttpUtils;
|
||||
import util.RSAUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class LogFileServiceImpl implements LogFileService {
|
||||
@Inject
|
||||
private LogFileConfig logFileConfig;
|
||||
@Inject
|
||||
private BaseConfig baseConfig;
|
||||
|
||||
@Override
|
||||
public void downloadLogFile() {
|
||||
String path = logFileConfig.getPath();
|
||||
log.info("开始下载日志文件: {}", path);
|
||||
|
||||
String username = baseConfig.getUsername();
|
||||
String password = baseConfig.getPassword();
|
||||
String gatewayUrl = baseConfig.getGatewayUrl();
|
||||
String publicKey = baseConfig.getPublicKey();
|
||||
try {
|
||||
// 使用RSA公钥加密密码
|
||||
String encryptedPassword = RSAUtil.encryptByPublicKey(password, publicKey);
|
||||
|
||||
log.info("密码已加密");
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("username", username);
|
||||
jsonObject.put("password", encryptedPassword);
|
||||
// 发送登录请求,使用加密后的密码
|
||||
String response = HttpUtils.http(gatewayUrl + "/sys/mLogin")
|
||||
.timeout(20)
|
||||
.bodyOfJson(jsonObject.toJSONString())
|
||||
.post();
|
||||
JSONObject body = JSONObject.parseObject(response);
|
||||
|
||||
log.info("登录返回: {}", body);
|
||||
boolean success = body.getBoolean("success");
|
||||
if (!success) {
|
||||
log.info("登录结果: {}", "失败");
|
||||
return;
|
||||
}
|
||||
String token = body.getJSONObject("result").getString("token");
|
||||
log.info("登录成功,获取到的token为: {}", token);
|
||||
|
||||
for (LogFileConfig.ServiceItem serviceItem : logFileConfig.getServices()) {
|
||||
String serviceName = serviceItem.getName();
|
||||
int insCount = serviceItem.getInsCount();
|
||||
log.info("开始下载服务: {}", serviceName);
|
||||
String downloadUrl = gatewayUrl + "/" + serviceName + "/service/log/files?service=" + serviceName;
|
||||
|
||||
try (HttpResponse resp = HttpUtils.http(downloadUrl).timeout(30).header("x-access-token", token).exec("GET")) {
|
||||
int code = resp.code();
|
||||
if (code != 200) {
|
||||
log.info("获取[{}]日志文件列表接口错误码: {}", serviceName, code);
|
||||
continue;
|
||||
}
|
||||
|
||||
String responseBody = resp.bodyAsString(); // 在流关闭前立即读取
|
||||
log.info("返回接口数据: {}", responseBody);
|
||||
JSONObject files = JSONObject.parseObject(responseBody);
|
||||
|
||||
// 修复:使用正确的对象检查success状态
|
||||
boolean serSuccess = files.getBoolean("success");
|
||||
if (!serSuccess) {
|
||||
log.info("获取日志文件结果: {}", "失败");
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONArray filesList = files.getJSONObject("result").getJSONArray("records");
|
||||
log.info("获取到的日志文件为: {}", filesList);
|
||||
|
||||
// 开始下载日志文件
|
||||
if (filesList != null && !filesList.isEmpty()) {
|
||||
Set<String> instanceSet = new HashSet<>();
|
||||
filesList.stream()
|
||||
.filter(JSONObject.class::isInstance)
|
||||
.map(JSONObject.class::cast)
|
||||
.map(file -> file.getString("instance"))
|
||||
.filter(Objects::nonNull)
|
||||
.map(instance -> instance.replace(".", "_").replace(":", "_")) // 替换 . 和 : 为 _
|
||||
.forEach(instanceSet::add);
|
||||
for (int i = 0; i < filesList.size(); i++) {
|
||||
JSONObject file = filesList.getJSONObject(i);
|
||||
String fileName = file.getString("fileName");
|
||||
String instance = file.getString("instance");
|
||||
String lastModified = file.getString("lastModified");
|
||||
|
||||
String filePath = path + "/" + serviceName;
|
||||
|
||||
log.info("开始下载日志文件: {}/{}", filePath, fileName);
|
||||
|
||||
String downloadFileUrl = gatewayUrl + "/" + serviceName + "/service/log/file/down?filename="
|
||||
+ fileName + "&instance=" + instance + "&service=" + serviceName;
|
||||
|
||||
|
||||
String instanceStr = instance.replace(":", "_").replace(".", "_");
|
||||
File downFile = new File(filePath + "/" + instanceStr + "_" + fileName);
|
||||
|
||||
|
||||
if (fileName.endsWith(".gz")) {//如果是压缩文件,说明已经归档压缩了,不会再改变,先查询一下本地是否存在,如果存在就跳过
|
||||
filePath = filePath + "/archive/";//压缩文件存放在archive目录下
|
||||
downFile = new File(filePath + "/" + instanceStr + "_" + fileName);
|
||||
if (downFile.exists()) {
|
||||
log.info("文件已存在,跳过下载: {}", downFile.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
//判断一下所有log文件更新日期,将小于今天的全部删除
|
||||
File[] logFiles = new File(filePath).listFiles((dir, name) ->
|
||||
name.endsWith(".log") || name.matches(".*\\.log\\.\\d{3}")
|
||||
);
|
||||
if (logFiles != null) {
|
||||
// 提前创建 /tmp/ 目录,避免重复创建
|
||||
File tmpBaseDir = new File(filePath + "/tmp/");
|
||||
if (!tmpBaseDir.exists()) {
|
||||
tmpBaseDir.mkdirs();
|
||||
}
|
||||
for (File logFile : logFiles) {
|
||||
try {
|
||||
long lastModifiedTime = logFile.lastModified();
|
||||
String lastDate = DateUtil.format(new Date(lastModifiedTime), "yyyy-MM-dd");
|
||||
String haveFileName = logFile.getName();
|
||||
// 判断是否需要移动文件(实例变化)
|
||||
// 判断 haveFileName 是否以 instanceSet 中任意一个实例开头
|
||||
boolean isMatched = instanceSet.stream().anyMatch(haveFileName::startsWith);
|
||||
int prefixesCount = countUniquePrefixes(filePath);//查询文件夹下有多少个不同前缀
|
||||
if (!isMatched && prefixesCount > insCount) {
|
||||
File mvDir = new File(tmpBaseDir, lastDate);
|
||||
if (!mvDir.exists()) {
|
||||
mvDir.mkdirs();
|
||||
}
|
||||
Files.move(logFile.toPath(), mvDir.toPath().resolve(haveFileName), StandardCopyOption.REPLACE_EXISTING);
|
||||
log.info("文件已移动至临时目录: {}", mvDir.toPath().resolve(haveFileName));
|
||||
continue; // 已移动的文件无需进一步处理
|
||||
}
|
||||
if (lastModifiedTime < getTodayStartTime()) {
|
||||
log.info("删除过期文件: {}", logFile.getAbsolutePath());
|
||||
logFile.delete();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("处理文件时发生错误: {}", logFile.getAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 在新的try-with-resources块中处理文件下载
|
||||
try (HttpResponse downloadRes = HttpUtils.http(downloadFileUrl)
|
||||
.header("x-access-token", token)
|
||||
.header("Content-Type", "application/octet-stream")
|
||||
.timeout(60).exec("GET")) {
|
||||
|
||||
int downloadCode = downloadRes.code();
|
||||
if (downloadCode != 200) {
|
||||
log.info("下载[{}]日志文件接口错误码: {}", serviceName, downloadCode);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 立即读取字节数据,在流关闭前完成
|
||||
byte[] bytes = downloadRes.bodyAsBytes();
|
||||
log.info("下载文件大小: {}", bytes.length);
|
||||
|
||||
|
||||
// 创建目录
|
||||
File downFileDir = new File(filePath);
|
||||
if (!downFileDir.exists()) {
|
||||
downFileDir.mkdirs(); // 修复:使用mkdirs()创建多级目录
|
||||
}
|
||||
|
||||
// 确保目录存在后再创建文件
|
||||
if (!downFile.getParentFile().exists()) {
|
||||
downFile.getParentFile().mkdirs();
|
||||
}
|
||||
//当天的文件.log结尾,如果有存在的文件,文件名加序号
|
||||
if (fileName.endsWith(".log")) {
|
||||
// 获取基础文件名(不包含序号部分)
|
||||
String baseFileName = getBaseFileNameWithoutSequence(downFile.getName());
|
||||
// 查找目标目录中所有匹配的基础文件名
|
||||
File parentDir = downFile.getParentFile();
|
||||
|
||||
FileInfo fileInfo = this.getFileInfo(parentDir, baseFileName);
|
||||
|
||||
//判断文件大小,如果本地文件大于线上文件,需要下载并重命名;如果本地文件小于线上文件,直接下载替换(本地文件以最大序号为准)
|
||||
long localFileSize = fileInfo.getFileSize();
|
||||
if (localFileSize == bytes.length) {
|
||||
log.info("文件已存在,跳过下载: {}", downFile.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
if (localFileSize > bytes.length) {
|
||||
downFile = new File(parentDir, fileInfo.getNextFileName());
|
||||
} else {
|
||||
downFile = new File(parentDir, fileInfo.getCurrentMaxFileName());
|
||||
}
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
try (FileOutputStream fos = new FileOutputStream(downFile)) {
|
||||
fos.write(bytes);
|
||||
log.info("成功下载文件: {}", downFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // 外层try-with-resources结束
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("下载日志文件过程中发生错误: ", e);
|
||||
throw new RuntimeException("下载日志文件失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取基础文件名(去除序列号部分)
|
||||
*/
|
||||
private String getBaseFileNameWithoutSequence(String fileName) {
|
||||
// 检查是否包含序号格式(如 .log.001)
|
||||
if (fileName.contains(".")) {
|
||||
String[] parts = fileName.split("\\.");
|
||||
if (parts.length >= 3) {
|
||||
// 检查倒数第二个部分是否为数字
|
||||
try {
|
||||
Integer.parseInt(parts[parts.length - 1]);
|
||||
// 返回去掉序号的部分
|
||||
StringBuilder baseName = new StringBuilder();
|
||||
for (int i = 0; i < parts.length - 1; i++) {
|
||||
if (i > 0) baseName.append(".");
|
||||
baseName.append(parts[i]);
|
||||
}
|
||||
return baseName.toString();
|
||||
} catch (NumberFormatException e) {
|
||||
// 不是数字,说明没有序号,返回原始名称
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个可用的序号
|
||||
*/
|
||||
private int getNextAvailableSequence(File directory, String baseFileName) {
|
||||
File[] existingFiles = directory.listFiles((dir, name) ->
|
||||
name.startsWith(baseFileName) &&
|
||||
(name.equals(baseFileName) || name.matches(baseFileName + "\\.\\d{3}")));
|
||||
|
||||
if (existingFiles == null) {
|
||||
return 1; // 目录不存在或无法访问
|
||||
}
|
||||
|
||||
int maxSequence = 0;
|
||||
|
||||
for (File file : existingFiles) {
|
||||
String fileName = file.getName();
|
||||
if (fileName.equals(baseFileName)) {
|
||||
// 基础文件存在,从1开始
|
||||
maxSequence = Math.max(maxSequence, 1);
|
||||
} else if (fileName.matches(baseFileName + "\\.\\d{3}")) {
|
||||
// 提取序号
|
||||
String sequencePart = fileName.substring(baseFileName.length() + 1); // +1 for the dot
|
||||
try {
|
||||
int sequence = Integer.parseInt(sequencePart);
|
||||
maxSequence = Math.max(maxSequence, sequence + 1);
|
||||
} catch (NumberFormatException e) {
|
||||
// 序号解析失败,跳过
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return maxSequence;
|
||||
}
|
||||
|
||||
|
||||
private long getTodayStartTime() {
|
||||
// 获取当前时间
|
||||
long currentTime = System.currentTimeMillis();
|
||||
// 计算今天0点的时间
|
||||
java.util.Calendar calendar = java.util.Calendar.getInstance();
|
||||
calendar.setTimeInMillis(currentTime);
|
||||
calendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(java.util.Calendar.MINUTE, 0);
|
||||
calendar.set(java.util.Calendar.SECOND, 0);
|
||||
calendar.set(java.util.Calendar.MILLISECOND, 0);
|
||||
return calendar.getTimeInMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前最大序号的文件名、下一个序号的文件名以及最大序号文件的大小
|
||||
*
|
||||
* @param directory 目标目录
|
||||
* @param baseFileName 基础文件名(不含序号)
|
||||
* @return FileInfo 包含当前最大序号文件名、下一个序号文件名和文件大小的信息
|
||||
*/
|
||||
private FileInfo getFileInfo(File directory, String baseFileName) {
|
||||
// 获取最大序号
|
||||
int maxSequence = getNextAvailableSequence(directory, baseFileName) - 1;
|
||||
|
||||
// 构建当前最大序号文件名
|
||||
String currentMaxFileName;
|
||||
if (maxSequence <= 0) {
|
||||
// 没有序号文件,直接使用基础文件名
|
||||
currentMaxFileName = baseFileName;
|
||||
} else {
|
||||
// 存在序号文件,拼接序号
|
||||
currentMaxFileName = baseFileName + "." + String.format("%03d", maxSequence);
|
||||
}
|
||||
|
||||
// 构建下一个序号文件名
|
||||
int nextSequence = maxSequence + 1;
|
||||
String nextFileName = baseFileName + "." + String.format("%03d", nextSequence);
|
||||
|
||||
// 构造当前最大序号文件对象
|
||||
File maxSequenceFile = new File(directory, currentMaxFileName);
|
||||
|
||||
// 检查文件是否存在并获取大小
|
||||
long fileSize = 0;
|
||||
if (maxSequenceFile.exists()) {
|
||||
fileSize = maxSequenceFile.length();
|
||||
}
|
||||
|
||||
// 返回封装好的信息
|
||||
return new FileInfo(currentMaxFileName, nextFileName, fileSize);
|
||||
}
|
||||
|
||||
public static int countUniquePrefixes(String directoryPath) {
|
||||
File directory = new File(directoryPath);
|
||||
if (!directory.exists() || !directory.isDirectory()) {
|
||||
log.info("目录不存在或不是一个有效目录: {}", directoryPath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Set<String> prefixSet = new HashSet<>();
|
||||
File[] files = directory.listFiles();
|
||||
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
String fileName = file.getName();
|
||||
// 提取最后一个 _ 前面的部分作为前缀
|
||||
int lastUnderscoreIndex = fileName.lastIndexOf('_');
|
||||
if (lastUnderscoreIndex != -1) {
|
||||
String prefix = fileName.substring(0, lastUnderscoreIndex);
|
||||
prefixSet.add(prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// log.info("唯一前缀数量: " + prefixSet.size());
|
||||
return prefixSet.size();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.renkang.rkutils.task;
|
||||
|
||||
import com.renkang.rkutils.service.LogFileService;
|
||||
import org.noear.solon.annotation.Component;
|
||||
import org.noear.solon.annotation.Inject;
|
||||
import org.noear.solon.scheduling.annotation.Scheduled;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class DownFileJob {
|
||||
|
||||
@Inject
|
||||
private LogFileService logFileService;
|
||||
@Scheduled(name = "downFileJob")
|
||||
public void downFile(){
|
||||
logFileService.downloadLogFile();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.renkang.rkutils.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileInfo {
|
||||
private String currentMaxFileName; // 当前最大序号的文件名
|
||||
private String nextFileName; // 下一个序号的文件名
|
||||
private long fileSize; // 最大序号文件的大小
|
||||
public FileInfo(String currentMaxFileName, String nextFileName, long fileSize) {
|
||||
this.currentMaxFileName = currentMaxFileName;
|
||||
this.nextFileName = nextFileName;
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package util;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
|
||||
public class RSAUtil {
|
||||
/**
|
||||
* 使用公钥加密
|
||||
*/
|
||||
public static String encryptByPublicKey(String data, String publicKeyStr) throws Exception {
|
||||
// 将公钥字符串转换为PublicKey对象
|
||||
byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr);
|
||||
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
|
||||
java.security.KeyFactory keyFactory = java.security.KeyFactory.getInstance("RSA");
|
||||
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
|
||||
|
||||
// 加密
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
byte[] encryptedData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
return Base64.getEncoder().encodeToString(encryptedData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
solon.config.load:
|
||||
- "conf/app-xj.yml"
|
||||
|
||||
solon.logging.appender:
|
||||
console:
|
||||
pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %magenta(${PID:-}) --- %-15([%15.15thread]) %-56(%cyan(%-40.40logger{39}%L)) : %msg%n"
|
||||
file:
|
||||
pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level ${PID:-} --- %-15([%15.15thread]) %-56(%-40.40logger{39}%L) : %msg%n"
|
||||
enable: true #是否启用
|
||||
extension: ".log" #v2.2.18 后支持(例:.log, .log.gz, .log.zip)
|
||||
maxFileSize: "10 MB"
|
||||
maxHistory: "7" #单位:天
|
||||
|
||||
solon.scheduling.job:
|
||||
downFileJob:
|
||||
cron: "0 30 * * * ?" # 每小时的第30分钟执行
|
||||
zone: "+08"
|
||||
fixedRate: 0
|
||||
# 任务间隔时间:1小时
|
||||
fixedDelay: 0
|
||||
initialDelay: 0
|
||||
enable: true #用任务进行启停控制
|
||||
|
||||
base:
|
||||
username: admin
|
||||
password: "#fCjW%x2dv@a"
|
||||
publicKey: "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmZfR/bA9X3vp86y1aEpvwzXJYKRRF1fLau2+05/ZtaITLpV8bhkmSf3neSy/Q9gAdvG75Fr73E+GWE+K5b0BpvIS1jDGo319+PpZR39SaZTKZ27XFXrosmJTZutN79t819HS1VseleunHAFgMVufE9U5jP6LGzl/wbkSy01GhzwIDAQAB"
|
||||
gatewayUrl: https://api-jkglpt.iosp.ydpt.tech
|
||||
# gatewayUrl: https://xj-api.mcrm.vip:8888
|
||||
file:
|
||||
path: D:/xjlogs
|
||||
services:
|
||||
- name: health-system
|
||||
insCount: 2
|
||||
# - health-watch
|
||||
Reference in New Issue
Block a user