diff --git a/modules/test/src/main/resources/domains/OperateType.xml b/modules/test/src/main/resources/domains/OperateType.xml
index aaea4e3..8feda08 100644
--- a/modules/test/src/main/resources/domains/OperateType.xml
+++ b/modules/test/src/main/resources/domains/OperateType.xml
@@ -1,7 +1,7 @@
-
+
@@ -10,5 +10,6 @@
+
diff --git a/modules/test/src/main/resources/views/actionGroup.xml b/modules/test/src/main/resources/views/actionGroup.xml
index 7f27303..a448e72 100644
--- a/modules/test/src/main/resources/views/actionGroup.xml
+++ b/modules/test/src/main/resources/views/actionGroup.xml
@@ -33,4 +33,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/test/src/main/resources/views/menu.xml b/modules/test/src/main/resources/views/menu.xml
index 9785193..55c6af0 100644
--- a/modules/test/src/main/resources/views/menu.xml
+++ b/modules/test/src/main/resources/views/menu.xml
@@ -5,6 +5,6 @@
-
+
diff --git a/src/main/java/com/system/log/LogTypeEnum.java b/src/main/java/com/system/log/LogTypeEnum.java
new file mode 100644
index 0000000..7549cfe
--- /dev/null
+++ b/src/main/java/com/system/log/LogTypeEnum.java
@@ -0,0 +1,23 @@
+package com.system.log;
+
+import com.hypaas.db.ValueEnum;
+import java.util.Objects;
+
+public enum LogTypeEnum implements ValueEnum {
+ Interface("Interface"),
+
+ Exception("Exception"),
+
+ Null("");
+
+ private final String value;
+
+ private LogTypeEnum(String value) {
+ this.value = Objects.requireNonNull(value);
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/system/log/SystemLog.java b/src/main/java/com/system/log/SystemLog.java
new file mode 100644
index 0000000..e444d31
--- /dev/null
+++ b/src/main/java/com/system/log/SystemLog.java
@@ -0,0 +1,22 @@
+package com.system.log;
+
+import static java.nio.file.StandardWatchEventKinds.*;
+
+import groovy.util.logging.Log4j;
+import java.io.*;
+import java.nio.file.*;
+
+@Log4j
+public class SystemLog {
+
+ public static void main(String[] args) throws Exception {
+ // String password = "zqy19.";
+ // //String regex = " ^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$";
+ // //String regex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@#$%^&+=]){6,16}$";
+ // String regex =
+ // "^(?![0-9A-Za-z]+$)(?![0-9A-Z\\W]+$)(?![0-9a-z\\W]+$)(?![A-Za-z\\W]+$)[0-9A-Za-z~!@#$%^&*()_+`\\-={}|\\[\\]\\\\:\";'<>?,./]{6,16}$";
+ // Pattern pattern = Pattern.compile(regex);
+ // Matcher matcher = pattern.matcher(password);
+ // System.out.println(matcher.find());
+ }
+}
diff --git a/src/main/java/com/system/log/controller/LogController.java b/src/main/java/com/system/log/controller/LogController.java
new file mode 100644
index 0000000..6f36091
--- /dev/null
+++ b/src/main/java/com/system/log/controller/LogController.java
@@ -0,0 +1,73 @@
+package com.system.log.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.inject.Inject;
+import com.google.inject.servlet.RequestScoped;
+import com.hypaas.db.JpaSupport;
+import com.hypaas.rpc.ActionRequest;
+import com.hypaas.rpc.ActionResponse;
+import com.system.log.core.FileUtils;
+import com.system.log.service.LogService;
+import java.io.File;
+import java.io.IOException;
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author zhangqiyang
+ * @description LogManage
+ * @date 2024/3/12
+ */
+@RequestScoped
+@Produces(MediaType.APPLICATION_JSON)
+@Path("/log")
+public class LogController extends JpaSupport {
+
+ @Inject LogService logService;
+
+ // 过滤查询日志接口
+ /*
+ * logType 日志类型
+ * startTime 需要过滤的日志的开始时间
+ * endTime 需要过滤的日志的结束时间
+ * keyWord 关键字
+ */
+ @GET
+ @Path("/getDirContent")
+ public JSONObject getDirContent(
+ @QueryParam("logType") String logType,
+ @QueryParam("startTime") String startTime,
+ @QueryParam("endTime") String endTime,
+ @QueryParam("keyWord") String keyWord)
+ throws IOException {
+ return logService.getDirContent(logType, startTime, endTime, keyWord);
+ }
+
+ // 以zip形式导出日志文件,并设置解压密码
+ /*
+ * password 密码
+ * conditionPassword 确认密码
+ * logType 日志类型
+ * startTime 需要过滤的日志的开始时间
+ * endTime 需要过滤的日志的结束时间
+ * keyWord 关键字
+ */
+
+ @POST
+ @Path("/getFileZip")
+ public void getFileZip(ActionRequest request, ActionResponse response) {
+ File file = logService.getFileZip(request, response);
+ FileUtils.downloadFile(response, file);
+ }
+
+ // @GET
+ // @Path("/getFile")
+ // public JSONObject getFileChange() {
+ // return logService.getFileChange();
+ // }
+
+ public void exportLog(ActionRequest request, ActionResponse response) {
+ File file = logService.exportLog(request, response);
+ FileUtils.downloadFile(response, file);
+ }
+}
diff --git a/src/main/java/com/system/log/core/FileUtils.java b/src/main/java/com/system/log/core/FileUtils.java
new file mode 100644
index 0000000..279cce7
--- /dev/null
+++ b/src/main/java/com/system/log/core/FileUtils.java
@@ -0,0 +1,97 @@
+package com.system.log.core;
+
+import com.hypaas.db.Query;
+import com.hypaas.i18n.I18n;
+import com.hypaas.inject.Beans;
+import com.hypaas.meta.MetaFiles;
+import com.hypaas.meta.db.MetaFile;
+import com.hypaas.meta.db.repo.MetaFileRepository;
+import com.hypaas.meta.schema.actions.ActionView;
+import com.hypaas.rpc.ActionResponse;
+import groovy.util.logging.Slf4j;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import javax.inject.Inject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** 文件工具类 获取项目中的文件 */
+@Slf4j
+public class FileUtils {
+
+ private static Logger logger = LoggerFactory.getLogger(FileUtils.class);
+
+ @Inject MetaFileRepository metaFileRepository;
+
+ /** 文件-导出File */
+ public static void downloadFile(ActionResponse response, File file) {
+ if (file == null) {
+ response.setError("文件不存在");
+ return;
+ }
+ try {
+ // 通过文件名查询是否存在
+ MetaFile metaFile =
+ Query.of(MetaFile.class)
+ .filter("self.fileName = :fileName")
+ .bind("fileName", file.getName())
+ .fetchOne();
+ if (metaFile == null) {
+ FileInputStream fileInputStream = new FileInputStream(file);
+ metaFile = Beans.get(MetaFiles.class).upload(file);
+ fileInputStream.close();
+ }
+
+ // 判断更改时间是否超过文件创建时间
+ long lastModified = file.lastModified();
+ LocalDateTime updateOn = metaFile.getUpdatedOn();
+ if (updateOn == null) {
+ updateOn = metaFile.getCreatedOn();
+ }
+ long createdOn = updateOn.toInstant(ZoneOffset.of("+8")).toEpochMilli();
+ if (lastModified > createdOn) {
+ FileInputStream fileInputStream = new FileInputStream(file);
+ metaFile = Beans.get(MetaFiles.class).upload(file, metaFile);
+ fileInputStream.close();
+ }
+
+ downloadMetaFile(response, metaFile);
+ } catch (FileNotFoundException fileNotFoundException) {
+ // logger.error("下载File文件时报错:", ExceptionUtils.getExceptionInfo(fileNotFoundException));
+ } catch (IOException ioException) {
+ // logger.error("下载File文件时报错:", ExceptionUtils.getExceptionInfo(ioException));
+ }
+ }
+
+ /**
+ * 文件-导出metaFile
+ *
+ * @param response:
+ * @param metaFile:
+ * @return
+ * @author huabiao
+ * @description
+ * @create 2022/2/18 8:52
+ */
+ public static void downloadMetaFile(ActionResponse response, MetaFile metaFile) {
+ if (metaFile == null) {
+ response.setError("文件不存在");
+ return;
+ }
+ response.setView(
+ ActionView.define(I18n.get("Export file"))
+ .model(MetaFile.class.getName())
+ .add(
+ "html",
+ "ws/rest/com.hypaas.meta.db.MetaFile/"
+ + metaFile.getId()
+ + "/content/download?v="
+ + metaFile.getVersion())
+ .param("download", "log.zip")
+ .map());
+ }
+}
diff --git a/src/main/java/com/system/log/listener/FileListener.java b/src/main/java/com/system/log/listener/FileListener.java
new file mode 100644
index 0000000..ce96b11
--- /dev/null
+++ b/src/main/java/com/system/log/listener/FileListener.java
@@ -0,0 +1,27 @@
+package com.system.log.listener;
+
+import java.io.File;
+import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
+import org.apache.commons.io.monitor.FileAlterationObserver;
+
+public class FileListener extends FileAlterationListenerAdaptor {
+
+ @Override
+ public void onStart(FileAlterationObserver observer) {
+ super.onStart(observer);
+ System.out.println("onStart");
+ }
+
+ @Override
+ public void onFileChange(File file) {
+ super.onFileChange(file);
+ String compressedPath = file.getAbsolutePath();
+ System.out.println("修改:" + compressedPath);
+ }
+
+ @Override
+ public void onStop(FileAlterationObserver observer) {
+ super.onStop(observer);
+ System.out.println("onStop");
+ }
+}
diff --git a/src/main/java/com/system/log/listener/FileMonitor.java b/src/main/java/com/system/log/listener/FileMonitor.java
new file mode 100644
index 0000000..a08a1ee
--- /dev/null
+++ b/src/main/java/com/system/log/listener/FileMonitor.java
@@ -0,0 +1,83 @@
+package com.system.log.listener;
+
+import java.io.File;
+import java.util.concurrent.TimeUnit;
+import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.apache.commons.io.filefilter.HiddenFileFilter;
+import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.io.monitor.FileAlterationMonitor;
+import org.apache.commons.io.monitor.FileAlterationObserver;
+
+public class FileMonitor {
+
+ private FileMonitor() {}
+
+ private static FileMonitor instance;
+
+ public static final FileMonitor getInstance() {
+ if (instance == null) {
+ synchronized (FileMonitor.class) {
+ if (instance == null) {
+ instance = new FileMonitor();
+ }
+ }
+ }
+ return instance;
+ }
+
+ // 设置监听路径
+ private final String monitorDir =
+ "C:\\Users\\张齐杨\\AppData\\Local\\JetBrains\\IntelliJIdea2023.2\\tomcat\\00f36d27-250c-4912-a029-744fef843e7c\\logs\\localhost_access_log.2024-03-21.txt";
+
+ // 设置轮询间隔
+ private final long interval = TimeUnit.SECONDS.toMillis(1);
+
+ public FileAlterationMonitor getMonitor() {
+ // 创建过滤器
+ // 1. 过滤可见目录
+ IOFileFilter directories =
+ FileFilterUtils.and(FileFilterUtils.directoryFileFilter(), HiddenFileFilter.VISIBLE);
+ // 2. 过滤以.txt结尾的文件,当该类型文件增删改时就会被监听到
+ IOFileFilter files =
+ FileFilterUtils.and(
+ FileFilterUtils.fileFileFilter(), FileFilterUtils.suffixFileFilter(".txt"));
+ // 两个筛选条件满足一个时就监听
+ IOFileFilter filter = FileFilterUtils.or(directories, files);
+
+ // 装配过滤器
+ FileAlterationObserver observer = new FileAlterationObserver(new File(monitorDir), filter);
+
+ // 向监听者添加监听器,并注入业务服务
+ observer.addListener(new FileListener());
+
+ // 返回监听者
+ return new FileAlterationMonitor(interval, observer);
+ }
+
+ // private FileAlterationMonitor monitor;
+ //
+ // public FileMonitor(long interval) {
+ // monitor = new FileAlterationMonitor(interval);
+ // }
+ //
+ // /**
+ // * 给文件添加监听
+ // *
+ // * @param path 文件路径
+ // * @param listener 文件监听器
+ // */
+ // public void monitor(String path, FileAlterationListener listener) {
+ // FileAlterationObserver observer = new FileAlterationObserver(new File(path));
+ // observer.addListener(listener);
+ // monitor.addObserver(observer);
+ // }
+ //
+ // public void stop() throws Exception {
+ // monitor.stop();
+ // }
+ //
+ // public void start() throws Exception {
+ // monitor.start();
+ //
+ // }
+}
diff --git a/src/main/java/com/system/log/service/LogService.java b/src/main/java/com/system/log/service/LogService.java
new file mode 100644
index 0000000..d2a9046
--- /dev/null
+++ b/src/main/java/com/system/log/service/LogService.java
@@ -0,0 +1,440 @@
+package com.system.log.service;
+
+import Log.LogEntity;
+import Log.repo.LogEntityRepository;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.google.inject.Inject;
+import com.hypaas.rpc.ActionRequest;
+import com.hypaas.rpc.ActionResponse;
+import com.system.log.LogTypeEnum;
+import com.system.log.vo.LogRecordVO;
+import java.io.*;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import net.lingala.zip4j.core.ZipFile;
+import net.lingala.zip4j.exception.ZipException;
+import net.lingala.zip4j.model.ZipParameters;
+import net.lingala.zip4j.util.Zip4jConstants;
+import org.apache.commons.lang3.StringUtils;
+
+public class LogService {
+
+ @Inject LogEntityRepository logEntityRepository;
+
+ public JSONObject getDirContent(String logType, String startTime, String endTime, String keyWord)
+ throws IOException {
+ // 定义集合,存放文件名称
+ List fileList;
+ // 获取Tomcat的CATALINA_BASE属性
+ String catalinaBase = System.getProperty("catalina.base");
+ // 获取localhost_access_log所在文件目录
+ String accessLogDir = catalinaBase + "\\logs";
+ // 找到过滤出的localhost_access_log文件,将文件的绝对路径放入集合中
+ fileList = getFilePath(accessLogDir, startTime, endTime);
+ // 获取所有文件下符合过滤条件内容并返回
+ return getFileContent(fileList, logType, startTime, endTime, keyWord);
+ }
+
+ // 找出文件夹下指定日志文件名并返回
+ private List getFilePath(String accessLogDir, String startTime, String endTime) {
+ // 定义集合,存放当前符合筛选条件的文件名
+ List filePathList = new ArrayList<>();
+ // 如果不传开始时间与结束时间,指定为null即可,默认输出当天的日志
+ if (StringUtils.isEmpty(startTime) && StringUtils.isEmpty(endTime)) {
+ // 以yyyy-MM-dd格式获取当天日期
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ String date = simpleDateFormat.format(new Date(System.currentTimeMillis()));
+ File LogFile = new File(accessLogDir);
+ File[] file = LogFile.listFiles();
+ for (File file1 : file) {
+ if (file1.toString().contains("localhost_access_log") && file1.toString().contains(date)) {
+ // 如果此文件是localhost_access_log文件并且是当天的文件,将其放入集合返回
+ filePathList.add(file1.getPath());
+ return filePathList;
+ }
+ }
+ } else {
+ filePathList = getFile(accessLogDir, startTime, endTime);
+ }
+ return filePathList;
+ }
+
+ // 使用日历类将符合条件的日志文件放入集合中返回
+ private List getFile(String accessLogDir, String startTime, String endTime) {
+ // 获取传入的开始时间与结束时间的毫秒数,开始时间直接将时分秒置零处理,结束时间将其加上一天后再将其置零处理,
+ // 这样做的目的是保证取出符合本次过滤时间的所有文件
+ List fileList = new ArrayList<>();
+ long[] time = getZeroLongTime(startTime, endTime);
+ // 遍历指定目录中的文件,筛选出符合条件的日志文件
+ File LogFile = new File(accessLogDir);
+ File[] file = LogFile.listFiles();
+ for (File file1 : file) {
+ if (file1.toString().contains("localhost_access_log")) {
+ // 如果文件名包含"localhost_access_log",则判断时间是否符合要求,如果符合,放入集合中
+ if ((getFileLongTime(file1.toString()) + 1000 > time[0])
+ && (getFileLongTime(file1.toString()) + 1000 < time[1])) {
+ fileList.add(file1.getPath());
+ }
+ }
+ }
+ return fileList;
+ }
+
+ // 获取文件名中的时间毫秒值
+ private long getFileLongTime(String fileName) {
+ Date date;
+ long milliseconds = 0;
+ String regex = "\\d{4}-\\d{2}-\\d{2}";
+ Pattern pattern = Pattern.compile(regex);
+ Matcher matcher = pattern.matcher(fileName);
+ if (matcher.find()) {
+ String time = matcher.group(0);
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+
+ try {
+ date = simpleDateFormat.parse(time);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ milliseconds = date.getTime();
+ }
+ return milliseconds;
+ }
+
+ // 输入开始时间与结束时间获得对应的零点毫秒数,方便筛选日志文件,必须以"yyyy-MM-dd HH:mm:ss"的形式输入
+ private long[] getZeroLongTime(String startTime, String endTime) {
+ // 用于存放毫秒数结果的数组
+ long[] longTime = new long[2];
+ Calendar calendar = Calendar.getInstance();
+ // 开始处理开始时间,得到毫秒值
+ calendar.set(Calendar.YEAR, Integer.parseInt(startTime.substring(0, 4)));
+ // 日历类中,00表示1月, 01表示2月,故应该减1
+ calendar.set(Calendar.MONTH, Integer.parseInt(startTime.substring(5, 7)) - 1);
+ calendar.set(Calendar.DATE, Integer.parseInt(startTime.substring(8, 10)));
+ // 这是将当天的【秒】设置为0
+ calendar.set(Calendar.SECOND, 0);
+ // 这是将当天的【分】设置为0
+ calendar.set(Calendar.MINUTE, 0);
+ // 这是将当天的【时】设置为0
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ longTime[0] = calendar.getTimeInMillis();
+ // 开始处理结束时间,得到毫秒值
+ calendar.set(Calendar.YEAR, Integer.parseInt(endTime.substring(0, 4)));
+ calendar.set(Calendar.MONTH, Integer.parseInt(endTime.substring(5, 7)) - 1);
+ calendar.set(Calendar.DATE, Integer.parseInt(endTime.substring(8, 10)) + 1);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ longTime[1] = calendar.getTimeInMillis();
+ return longTime;
+ }
+
+ // 输入开始时间与结束时间获得对应的标准毫秒数,方便筛选每个日志文件中的数据,必须以"yyyy-MM-dd HH:mm:ss"的形式输入
+ private long getLongTime(String time) {
+ Date date;
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ try {
+ date = simpleDateFormat.parse(time);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ return date.getTime();
+ }
+
+ // 获取
+ private long getLogContentLongTime(String logContent) {
+ Date date;
+ SimpleDateFormat simpleDateFormat =
+ new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss", Locale.ENGLISH);
+ try {
+ // 取出日志文件中例如22/Feb/2024:10:04:32 +0800的部分,转化为毫秒
+ date =
+ simpleDateFormat.parse(
+ logContent.substring(logContent.indexOf("[") + 1, logContent.indexOf("[") + 21));
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ return date.getTime();
+ }
+
+ // 返回日志文件的详细内容(StringBuffer)
+ private JSONObject getFileContent(
+ List fileList, String logType, String startTime, String endTime, String keyWord) {
+ JSONArray jsonArray = new JSONArray();
+ if (StringUtils.isEmpty(logType)) {
+ logType = "";
+ }
+ if (StringUtils.isEmpty(keyWord)) {
+ keyWord = "";
+ }
+ for (String file : fileList) {
+ try {
+ // 设置读取器,读取fileList中的文件
+ BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
+ String line;
+ // 如果开始时间与结束时间为空,则fileList里只有一个当天的日志文件,不需要时间过滤,只过滤日志类型与关键字即可
+ if (StringUtils.isEmpty(startTime) && StringUtils.isEmpty(endTime)) {
+ // 判断下一行不为空就读取出来进行条件判断
+ while ((line = bufferedReader.readLine()) != null) {
+ // 判断本行数据是否包含输入的日志类型与关键字信息,如果包含,写入文件
+ if (LogTypeEnum.Interface.getValue().equals(logType)) {
+ if ((!line.contains(LogTypeEnum.Exception.getValue())) && line.contains(keyWord)) {
+ jsonArray.add(logAnalysis(line, file));
+ }
+ } else {
+ if (line.contains(logType) && line.contains(keyWord)) {
+ jsonArray.add(logAnalysis(line, file));
+ }
+ }
+ }
+ } else {
+ // 如果开始时间与结束时间不为空,则fileList里不确定有几个日志文件,由于考虑精确到时分秒,需要时间过滤,
+ // 还需要过滤日志类型与关键字
+ while ((line = bufferedReader.readLine()) != null) {
+ if (LogTypeEnum.Interface.getValue().equals(logType)) {
+ if (getLongTime(startTime) <= getLogContentLongTime(line)
+ && getLongTime(endTime) >= getLogContentLongTime(line)
+ && ((!line.contains(LogTypeEnum.Exception.getValue()))
+ && line.contains(keyWord))) {
+ jsonArray.add(logAnalysis(line, file));
+ }
+ } else {
+ if (getLongTime(startTime) <= getLogContentLongTime(line)
+ && getLongTime(endTime) >= getLogContentLongTime(line)
+ && (line.contains(logType) && line.contains(keyWord))) {
+ jsonArray.add(logAnalysis(line, file));
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.getStackTrace();
+ }
+ }
+ JSONObject jsonObject = new JSONObject();
+ JSONObject selectContent = new JSONObject();
+ jsonObject.put("code", 200);
+ jsonObject.put("msg", "操作成功");
+ selectContent.put("content", jsonArray);
+ jsonObject.put("data", selectContent);
+ return jsonObject;
+ }
+
+ // 解析日志,提取关键信息
+ private JSONObject logAnalysis(String logContent, String fileName) {
+ JSONObject logDetail = new JSONObject();
+ LogRecordVO logRecordVO = new LogRecordVO();
+ SimpleDateFormat simpleDateFormat =
+ new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss", Locale.ENGLISH);
+ try {
+ // 以yyyy-MM-dd HH:mm:ss形式提取时间
+ long l =
+ simpleDateFormat
+ .parse(
+ logContent.substring(logContent.indexOf("[") + 1, logContent.indexOf("[") + 21))
+ .getTime();
+ SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ String date = simpleDateFormat1.format(l);
+ logRecordVO.setTime(date);
+ // 提取ip地址
+ String ipAddress = logContent.substring(0, logContent.indexOf("-") - 1);
+ logRecordVO.setIpAddress(ipAddress);
+ // 写入文件名l
+ logRecordVO.setFileSource(fileName);
+ // 写入文件内容
+ String log =
+ logContent.substring(logContent.indexOf("]") + 2, logContent.length()).replace("\"", "");
+ logRecordVO.setLogContent(log);
+ return (JSONObject) JSONObject.toJSON(logRecordVO);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public File getFileZip(ActionRequest request, ActionResponse response) {
+ String password = request.getContext().get("password").toString();
+ String confirmPassword = request.getContext().get("confirmPassword").toString();
+ String startTime = request.getContext().get("startTime").toString();
+ String endTime = request.getContext().get("endTime").toString();
+ String logType = request.getContext().get("logType").toString();
+ String keyWord = request.getContext().get("keyWord").toString();
+ // 判断密码和确认密码是否都不为空且一致,如果不一致直接返回null
+ if (StringUtils.isEmpty(password)
+ || StringUtils.isEmpty(confirmPassword)
+ || !password.equals(confirmPassword)) {
+ return null;
+ }
+
+ // 定义集合,存放文件名称
+ List fileList;
+ // 获取Tomcat的CATALINA_BASE属性
+ String catalinaBase = System.getProperty("catalina.base");
+ // 获取localhost_access_log所在文件目录
+ String accessLogDir = catalinaBase + "\\logs";
+ // 找到过滤出的localhost_access_log文件,将文件的绝对路径放入集合中
+ fileList = getFilePath(accessLogDir, startTime, endTime);
+ // 查询出所有的记录
+ JSONObject selectResult = getFileContent(fileList, logType, startTime, endTime, keyWord);
+
+ try {
+ // 创建临时文件,将查询的结果写入临时文件
+ File tempFile = File.createTempFile("log", ".txt");
+ FileWriter writer = new FileWriter(tempFile);
+ writer.write(selectResult.toString());
+ writer.close();
+
+ // 根据时间设定输出文件名
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
+ String date = simpleDateFormat.format(new Date(System.currentTimeMillis()));
+
+ // 获取临时文件目录
+ String tempDir = System.getProperty("java.io.tmpdir");
+ String tempFilePath = tempDir + "/" + date + ".zip";
+ System.out.println(tempFilePath);
+ // 在临时文件目录中创建一个随机名称的zip文件
+ File file = new File(tempFilePath);
+ ZipFile zipFile = new ZipFile(file);
+ ZipParameters parameters = new ZipParameters(); // 设置zip包的一些参数集合
+ parameters.setEncryptFiles(true); // 是否设置密码(此处设置为:是)
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // 压缩方式(默认值)
+ parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); // 普通级别(参数很多)
+ parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD); // 加密级别
+ parameters.setPassword(password); // 压缩包密码
+ // 向zip文件中根据设置的参数写入数据
+ zipFile.createZipFile(tempFile, parameters);
+ return file;
+ } catch (ZipException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // public JSONObject getFileChange() {
+ // // 定义集合,存放文件名称
+ // List fileList;
+ // // 获取Tomcat的CATALINA_BASE属性
+ // String catalinaBase = System.getProperty("catalina.base");
+ // // 获取localhost_access_log所在文件目录
+ // String accessLogDir = catalinaBase + "\\logs";
+ // // 找到过滤出的localhost_access_log文件,将文件的绝对路径放入集合中
+ // fileList = getFilePath(accessLogDir, null, null);
+ // // 返回当天日志文件
+ // return getFileContent(fileList, null, null, null, null);
+ // }
+
+ public File exportLog(ActionRequest request, ActionResponse response) {
+ String password = request.getContext().get("password").toString();
+ String confirmPassword = request.getContext().get("confirmPassword").toString();
+ String startTime = request.getContext().get("exportStartTime").toString();
+ String endTime = request.getContext().get("exportEndTime").toString();
+ if (!password.equals(confirmPassword)) {
+ return null;
+ }
+ // 密码正则表达式校验
+ String regex =
+ "^(?![0-9A-Za-z]+$)(?![0-9A-Z\\W]+$)(?![0-9a-z\\W]+$)(?![A-Za-z\\W]+$)[0-9A-Za-z~!@#$%^&*()_+`\\-={}|\\[\\]\\\\:\";'<>?,./]{6,16}$";
+ Pattern pattern = Pattern.compile(regex);
+ Matcher matcher = pattern.matcher(password);
+ if (!matcher.find()) {
+ // 密码不通过正则校验
+ response.setAlert("密码需要包含6-16位数字+大写字母+小写字母+特殊字符!");
+ }
+
+ List selectResult = new ArrayList<>();
+ List logEntitiesList = logEntityRepository.all().fetch();
+ if (startTime != null && endTime != null) {
+ // 如果输入的开始时间与结束时间都不为空,则输出时间范围内的所有记录
+ for (LogEntity logEntity : logEntitiesList) {
+ if ((getSqlLongTime(logEntity.getTime()) > getSqlLongTime(startTime))
+ && (getSqlLongTime(logEntity.getTime()) < getSqlLongTime(endTime))) {
+ selectResult.add(logEntity);
+ }
+ }
+ }
+
+ if (startTime == null && endTime != null) {
+ // 如果输入的开始时间为空,则输出结束时间之前的所有记录
+ for (LogEntity logEntity : logEntitiesList) {
+ if ((getSqlLongTime(logEntity.getTime()) < getSqlLongTime(endTime))) {
+ selectResult.add(logEntity);
+ }
+ }
+ }
+
+ if (startTime != null && endTime == null) {
+ // 如果输入的结束时间为空,则输出开始时间之后的所有记录
+ for (LogEntity logEntity : logEntitiesList) {
+ if ((getSqlLongTime(logEntity.getTime()) > getSqlLongTime(startTime))) {
+ selectResult.add(logEntity);
+ }
+ }
+ }
+
+ if (startTime == null && endTime == null) {
+ // 如果输入的时间都为空,则输出所有记录
+ for (LogEntity logEntity : logEntitiesList) {
+ selectResult.add(logEntity);
+ }
+ }
+ Object jsonObject = JSONObject.toJSON(selectResult);
+ return exportLogZip(jsonObject, password);
+ }
+
+ private long getSqlLongTime(Object time) {
+ // logEntity.getTime()形式 "2024-02-04T14:03:45.114"
+ // startTime()形式 "2024-02-04 14:03"
+ Date date;
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ if (time.toString().length() < 19) {
+ time = time.toString().replace("T", " ") + ":00";
+ } else {
+ time = time.toString().substring(0, 19).replace("T", " ");
+ }
+ try {
+ date = simpleDateFormat.parse(time.toString());
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ return date.getTime();
+ }
+
+ public File exportLogZip(Object selectResult, String password) {
+ try {
+ // 创建临时文件,将查询的结果写入临时文件
+ File tempFile = File.createTempFile("log", ".txt");
+ FileWriter writer = new FileWriter(tempFile);
+ writer.write(selectResult.toString());
+ writer.close();
+
+ // 根据时间设定输出文件名
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
+ String date = simpleDateFormat.format(new Date(System.currentTimeMillis()));
+
+ // 获取临时文件目录
+ String tempDir = System.getProperty("java.io.tmpdir");
+ String tempFilePath = tempDir + "/" + date + ".zip";
+ System.out.println(tempFilePath);
+ // 在临时文件目录中创建一个随机名称的zip文件
+ File file = new File(tempFilePath);
+ ZipFile zipFile = new ZipFile(file);
+ ZipParameters parameters = new ZipParameters(); // 设置zip包的一些参数集合
+ parameters.setEncryptFiles(true); // 是否设置密码(此处设置为:是)
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // 压缩方式(默认值)
+ parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); // 普通级别(参数很多)
+ parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD); // 加密级别
+ parameters.setPassword(password); // 压缩包密码
+ // 向zip文件中根据设置的参数写入数据
+ zipFile.createZipFile(tempFile, parameters);
+ return file;
+ } catch (ZipException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/main/java/com/system/log/vo/LogRecordVO.java b/src/main/java/com/system/log/vo/LogRecordVO.java
new file mode 100644
index 0000000..1b3fa9a
--- /dev/null
+++ b/src/main/java/com/system/log/vo/LogRecordVO.java
@@ -0,0 +1,43 @@
+package com.system.log.vo;
+
+import lombok.Data;
+
+@Data
+public class LogRecordVO {
+ private String time;
+ private String ipAddress;
+ private String fileSource;
+ private String logContent;
+
+ public String getTime() {
+ return time;
+ }
+
+ public void setTime(String time) {
+ this.time = time;
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ public String getFileSource() {
+ return fileSource;
+ }
+
+ public void setFileSource(String fileSource) {
+ this.fileSource = fileSource;
+ }
+
+ public String getLogContent() {
+ return logContent;
+ }
+
+ public void setLogContent(String logContent) {
+ this.logContent = logContent;
+ }
+}
diff --git a/src/main/java/com/system/log/vo/ZipInfo.java b/src/main/java/com/system/log/vo/ZipInfo.java
new file mode 100644
index 0000000..75541f7
--- /dev/null
+++ b/src/main/java/com/system/log/vo/ZipInfo.java
@@ -0,0 +1,9 @@
+package com.system.log.vo;
+
+import lombok.Data;
+
+@Data
+public class ZipInfo {
+ private String fileName;
+ private String filePath;
+}