zhangqiyang
8 months ago
12 changed files with 829 additions and 2 deletions
@ -0,0 +1,23 @@
|
||||
package com.system.log; |
||||
|
||||
import com.hypaas.db.ValueEnum; |
||||
import java.util.Objects; |
||||
|
||||
public enum LogTypeEnum implements ValueEnum<String> { |
||||
Interface("Interface"), |
||||
|
||||
Exception("Exception"), |
||||
|
||||
Null(""); |
||||
|
||||
private final String value; |
||||
|
||||
private LogTypeEnum(String value) { |
||||
this.value = Objects.requireNonNull(value); |
||||
} |
||||
|
||||
@Override |
||||
public String getValue() { |
||||
return value; |
||||
} |
||||
} |
@ -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());
|
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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()); |
||||
} |
||||
} |
@ -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"); |
||||
} |
||||
} |
@ -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();
|
||||
//
|
||||
// }
|
||||
} |
@ -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<String> 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<String> getFilePath(String accessLogDir, String startTime, String endTime) { |
||||
// 定义集合,存放当前符合筛选条件的文件名
|
||||
List<String> 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<String> getFile(String accessLogDir, String startTime, String endTime) { |
||||
// 获取传入的开始时间与结束时间的毫秒数,开始时间直接将时分秒置零处理,结束时间将其加上一天后再将其置零处理,
|
||||
// 这样做的目的是保证取出符合本次过滤时间的所有文件
|
||||
List<String> 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<String> 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<String> 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<String> 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<LogEntity> selectResult = new ArrayList<>(); |
||||
List<LogEntity> 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); |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
Loading…
Reference in new issue