一、前言
在开发中,需要检验cron表达式的合法性以及获取执行时间。在CronUtils中实现了这些功能。
二、引入maven依赖
<dependency>
<groupId>com.cronutils</groupId>
<artifactId>cron-utils</artifactId>
<version>9.1.5</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
二、建工具类 CronUtils
import com.cronutils.descriptor.CronDescriptor;
import com.cronutils.model.Cron;
import com.cronutils.model.CronType;
import com.cronutils.model.definition.CronDefinition;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.model.time.ExecutionTime;
import com.cronutils.parser.CronParser;
public class CronUtils {
public static void main(String[] args) {
String expression = "0 0 0 ? 5 2#1";
expression = "0 0 12 7 * ?";
//格式校验
boolean b = checkCronValid(expression);
System.out.println(b);
if (b) {
//解释cron表达式
String s = describeCron(expression);
System.out.println(s);
//获取下次运行时间
List<Date> nextExecTime = null;
try {
nextExecTime = getNextExecTime(expression, 1);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Optional.of(nextExecTime).ifPresent( n -> n.stream().forEach(d -> {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(d));
}));
System.err.println(parseCronToExeTime(expression));
}
}
/**
* 解释cron表达式
*/
public static String describeCron(String expression) {
CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
CronParser parser = new CronParser(cronDefinition);
Cron cron = parser.parse(expression);
//设置语言
CronDescriptor descriptor = CronDescriptor.instance(Locale.CHINESE);
return descriptor.describe(cron);
}
/**
* 解析cron转化为执行时间
* @param expressiion
* @return
*/
public static String parseCronToExeTime(String expression) {
CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.SPRING);
CronParser parser = new CronParser(cronDefinition);
Cron cron = parser.parse(expression);
ExecutionTime exeTime=ExecutionTime.forCron(cron);
ZonedDateTime now = ZonedDateTime.now();
//根据当前时间获取下次执行时间
ZonedDateTime next = exeTime.nextExecution(now).get();
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
return next.format(format);
}
/**
* @param cronExpression cron表达式
* @param numTimes 下一(几)次运行的时间
* @return
*/
public static List<Date> getNextExecTime(String cronExpression, Integer numTimes) throws ParseException {
CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();
cronTriggerImpl.setCronExpression(cronExpression);
// 这个是重点,一行代码搞定
return TriggerUtils.computeFireTimes(cronTriggerImpl, null, numTimes);
}
/**
* 检查cron表达式的合法性
*
* @param cron cron exp
* @return true if valid
*/
public static boolean checkCronValid(String cron) {
try {
return CronExpression.isValidExpression(cron);
} catch (Exception e) {
System.out.println(String.format("cron=%s not valid", cron));
return false;
}
}
}
三、具体使用
在实际接口中,我们也会使用到,比如我们新建了个调度组,调度执行任务,那么我们可能就需要解析cron的表达式,得到下次执行的时间。
首先新建调度组entity
/**
* 调度组
* @author Lenovo
*
*/
public class SchedulerGroup {
private Integer groupId;
private String groupName;
private String cronExpression;
private String execTime;
}
接下来编写相关业务代码
import java.util.List;
import entity.SchedulerGroup;
import utils.CronUtils;
@Service
public class SchedulerGroupService {
@Autowire
private SchedulerGroupMapper schedulerGroupMapper;
public List<SchedulerGroup> querySchedulerGroup() {
List<SchedulerGroup> groupList = schedulerGroupMapper.selectList();
for(SchedulerGroup group : groupList) {
String execTime = CronUtils.parseCronToExeTime(group.getCronExpression());
group.setExecTime(execTime);
}
return groupList;
}
}
上面是查询调度组列表,需展示下次调度执行时间。
当然,我们在创建的时候,也需校验cron表达式是否合法,调用工具类中的checkCronValid() 方法校验即可,一般不建议用正则表达式匹配验证cron表达式,一是匹配规则太复杂几乎没法修改,二是容易出错,所以强烈建议你使用CronExpression包进行验证。