关于清理日志相关属性的配置
为了方便配置,日志的原有路径和备份路径等配置我们定义在propies文件中,然后通过spring的注解value来获取
#日志清理配置
original.log.path=/data/logs/sspapi-job
log.back.path=/data/logs/sspapi-job/back
back.log.date=30
delete.log.date=35
log.name.prefix=test_log
@Value("${original.log.path}")
private String originalLogPath;
@Value("${log.back.path}")
private String logBackPath;
@Value("${log.name.prefix}")
private String logNamePrefix;
@Value("${back.log.date}")
private int backLogDate;
@Value("${delete.log.date}")
private int deleteLogDate;
清理前的准备
由于配置有错误可能,以及目录存在的实际情况,为了保证程序的健壮性,必要的校验是必不可少的
//判断删除和备份日期是否配置正确
if (backLogDate>=deleteLogDate||backLogDate<1||deleteLogDate<1){
log.error("删除和备份时间配置不正确");
return false;
}
//判断原有日志目录是否存在
File originalLogDir = new File(originalLogPath);
if (!originalLogDir.isDirectory()){
log.error("原有日志路径不存在");
return false;
}
//若备份目录不存在,创建
File logBackDir = new File(logBackPath);
if (logBackDir.isFile()){
log.error("备份目录为一个文件");
return false;
}
if (!logBackDir.exists()){
if (!logBackDir.mkdirs()){
log.error("备份目录创建失败");
return false;
}
}
具体备份及删除策略
日志删除和备份策略具体体现为,根据日志的文件名中包含的时间信息,获得与当前时间的差值,与配置文件中的备份时间和删除时间对比,做不同处理。具体处理逻辑需根据需求和文件名格式有所不同,下面是一个简单的demo
public boolean execute(String param) {
//判断删除和备份日期是否配置正确
if (backLogDate>=deleteLogDate||backLogDate<1||deleteLogDate<1){
log.error("删除和备份时间配置不正确");
return false;
}
//判断原有日志目录是否存在
File originalLogDir = new File(originalLogPath);
if (!originalLogDir.isDirectory()){
log.error("原有日志路径不存在");
return false;
}
//若备份目录不存在,创建
File logBackDir = new File(logBackPath);
if (logBackDir.isFile()){
log.error("备份目录为一个文件");
return false;
}
if (!logBackDir.exists()){
if (!logBackDir.mkdirs()){
log.error("备份目录创建失败");
return false;
}
}
//遍历原有日志路径下的文件,将符合格式的进行备份
File[] originalLogs = originalLogDir.listFiles();
for (File logFile:originalLogs) {
if (logFile.isFile()&&logFile.getName().startsWith(logNamePrefix)){
dealFile(logFile,MOVE_CODE);
}
}
//遍历备份路径下的文件,进行删除
File[] backFiles = logBackDir.listFiles();
for (File logFile:backFiles){
if (logFile.isFile()){
dealFile(logFile,DELETE_CODE);
}
}
return true;
}
/**
* 处理单个文件
* @param logFile 需处理的文件
* @param operationType 操作类型,1为移动备份,2为删除
*/
private void dealFile(File logFile,int operationType) {
String fileName = logFile.getName();
Date fileDate = getDateStr(fileName);
//针对格式不正确的文件,保留
if (null == fileDate){
return;
}
//获取当前时间与文件名中的时间的天数差值
int days = ((int) (new Date().getTime() / 1000) - (int) (fileDate.getTime() / 1000)) / (60 * 60 * 24);
//比较文件日期和当前日期,超过指定日期的移动到备份目录
if (MOVE_CODE == operationType){
if (days>backLogDate){
logFile.renameTo(new File(logBackPath+File.separator+logFile.getName()));
}
}else if (DELETE_CODE == operationType){
if (days>deleteLogDate){
logFile.delete();
}
}
}
/**
* 取出文件名中代表日期的字段,转换为日期格式
* @param fileName
* @return
*/
private Date getDateStr(String fileName) {
String[] fileNameParts = fileName.split("\\.");
if (fileNameParts.length<3){
log.debug("不是需要删除的文件,文件名: {}",fileName);
return null;
}
Date fileDate = null;
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
try {
String dateStr = fileNameParts[1];
fileDate = sdf.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
log.debug("不是需要删除的文件,文件名: {}",fileName);
}
return fileDate;
}
日志清理任务的执行
通常来说,日志清理任务是通过定时任务来执行的,定时任务的有许多框架,spring-task,quartz等,这次我们已spring-task作为我们定时任务的载体,
只需在方法上加入注解
@Scheduled(cron = “0/30 * * * * ?”)
使用spring boot需只在spring的启动类上加入注解@EnableScheduling即可开启定时任务
========================================
spring cron表达式 简介
关于 cronExpression 表达式有至少 6 个(也可能是 7 个)由空格分隔的时间元素。
//感觉基本上是6个,7个好像没成功过
字段 允许值 允许的特殊字符
- 秒 0-59 , - * /
- 分 0-59 , - * /
- 小时 0-23 , - * /
- 日期 1-31 , - * ? / L W C
- 月份 1-12 或者 JAN-DEC , - * /
- 星期 1-7 或者 SUN-SAT , - * ? / L C #
- 年(可选)留空, 1970-2099 , - * /
- 区间
- 通配符
? 不想设置那个字段12345678910111213
Seconds:可出现,- * / 四个字符,有效范围为0-59的整数
Minutes:可出现,- * / 四个字符,有效范围为0-59的整数
Hours:可出现,- * / 四个字符,有效范围为0-23的整数
DayofMonth:可出现,- * / ? L W C八个字符,有效范围为0-31的整数
Month:可出现,- * / 四个字符,有效范围为1-12的整数或JAN-DEc
DayofWeek:可出现,- * / ? L C #四个字符,有效范围为1-7的整数或SUN-SAT两个范围。1表示星期天,2表示星期一, 依次类推
Year:可出现,- * / 四个字符,有效范围为1970-2099年