Java CronSequenceGenerator的解决方案是每月的最后一天?

Java CronSequenceGenerator的解决方案是每月的最后一天?,java,spring,spring-mvc,scheduled-tasks,cronexpression,Java,Spring,Spring Mvc,Scheduled Tasks,Cronexpression,好的,我想安排一个任务在每个月的最后一天上午10:10运行 0 10 10 L * ? 现在的问题是为“L”值抛出NumberFormatException。这意味着Spring的CronSequenceGenerator不支持这种表达式。如何以任何其他方式做到这一点(解决方法)。我不想使用quartz,或者Spring会在新版本中支持这一点 以下是完整的stacktrace: Exception in thread "main" java.lang.NumberFormatException

好的,我想安排一个任务在每个月的最后一天上午10:10运行

0 10 10 L * ?
现在的问题是为“L”值抛出NumberFormatException。这意味着Spring的CronSequenceGenerator不支持这种表达式。如何以任何其他方式做到这一点(解决方法)。我不想使用quartz,或者Spring会在新版本中支持这一点

以下是完整的stacktrace:

Exception in thread "main" java.lang.NumberFormatException: For input string: "L"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:492)
    at java.lang.Integer.valueOf(Integer.java:582)
    at org.springframework.scheduling.support.CronSequenceGenerator.getRange(CronSequenceGenerator.java:324)
    at org.springframework.scheduling.support.CronSequenceGenerator.setNumberHits(CronSequenceGenerator.java:297)
    at org.springframework.scheduling.support.CronSequenceGenerator.setDays(CronSequenceGenerator.java:275)
    at org.springframework.scheduling.support.CronSequenceGenerator.setDaysOfMonth(CronSequenceGenerator.java:266)
    at org.springframework.scheduling.support.CronSequenceGenerator.parse(CronSequenceGenerator.java:239)
    at org.springframework.scheduling.support.CronSequenceGenerator.<init>(CronSequenceGenerator.java:81)
    at org.springframework.scheduling.support.CronTrigger.<init>(CronTrigger.java:54)
    at org.springframework.scheduling.support.CronTrigger.<init>(CronTrigger.java:44)
    at com.hcdc.coedp.datantar.scheduler.SchedulerUtil.start(SchedulerUtil.java:75)
    at com.hcdc.coedp.datantar.scheduler.SchedulerUtil.changeTrigger(SchedulerUtil.java:106)
    at com.hcdc.coedp.datantar.scheduler.SchedulingService.scheduleTransfer(SchedulingService.java:70)
    at com.hcdc.coedp.datantar.scheduler.Scheduler.schedule(Scheduler.java:107)
    at main.Main.main(Main.java:47)
线程“main”java.lang.NumberFormatException中的异常:对于输入字符串:“L” 位于java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) 位于java.lang.Integer.parseInt(Integer.java:492) 位于java.lang.Integer.valueOf(Integer.java:582) 位于org.springframework.scheduling.support.CronSequenceGenerator.getRange(CronSequenceGenerator.java:324) 位于org.springframework.scheduling.support.CronSequenceGenerator.setNumberHits(CronSequenceGenerator.java:297) 位于org.springframework.scheduling.support.CronSequenceGenerator.setDays(CronSequenceGenerator.java:275) 位于org.springframework.scheduling.support.CronSequenceGenerator.setDaysOfMonth(CronSequenceGenerator.java:266) 位于org.springframework.scheduling.support.CronSequenceGenerator.parse(CronSequenceGenerator.java:239) 位于org.springframework.scheduling.support.CronSequenceGenerator(CronSequenceGenerator.java:81) 位于org.springframework.scheduling.support.CronTrigger.(CronTrigger.java:54) 位于org.springframework.scheduling.support.CronTrigger.(CronTrigger.java:44) 位于com.hcdc.coedp.datantar.SchedulerUtil.start(SchedulerUtil.java:75) 位于com.hcdc.coedp.datantar.SchedulerUtil.changeTrigger(SchedulerUtil.java:106) 位于com.hcdc.coedp.datantar.scheduler.SchedulingService.scheduleTransfer(SchedulingService.java:70) 位于com.hcdc.coedp.datantar.scheduler.scheduler.schedule(scheduler.java:107) 在main.main.main(main.java:47) 更新:

以下是我的日程安排方法

 /**
    * Schedule a task {@link Task} with a specified cron expression.
    * @param task {@link Task}
    * @param cronExpression cron expression to be applied must be a vaild one.
    * @param taskName
    * @return 
    */
     public String start(Task task, String cronExpression, String taskName) {
        CronTrigger trigger = new CronTrigger(cronExpression);//line 2

        CronSequenceGenerator generator = new CronSequenceGenerator(cronExpression, TimeZone.getTimeZone("GMT+5:30"));
        List<Date> dateList = new ArrayList<>(5);
        Date currentDate = new Date();
        for (int i = 0; i < 5; i++) {
            currentDate = generator.next(currentDate);
            dateList.add((currentDate));
            System.out.println("Next Exceution times are" + currentDate);
        }
        ScheduledFuture sf = tps.schedule(task, trigger);

        //TODO Save this scheduled future with a specific task name.
        ContextHolder.schduledFutureMap.put(taskName, sf);
        return cronExpression;
    }
/**
*使用指定的cron表达式计划任务{@link task}。
*@param task{@link task}
*@param cronExpression要应用的cron表达式必须是有效的。
*@param taskName
*@返回
*/
公共字符串开始(任务任务、字符串表达式、字符串任务名){
CronTrigger=新的CronTrigger(cronExpression);//第2行
CronSequenceGenerator=新的CronSequenceGenerator(cronExpression,TimeZone.getTimeZone(“GMT+5:30”);
列表日期列表=新的ArrayList(5);
日期currentDate=新日期();
对于(int i=0;i<5;i++){
currentDate=发电机。下一个(currentDate);
添加((当前日期));
System.out.println(“下一个执行时间为“+当前日期”);
}
ScheduledFuture sf=tps.schedule(任务、触发器);
//TODO使用特定任务名称保存此计划的未来。
ContextHolder.scheduledfuturemap.put(taskName,sf);
返回表达式;
}

在第2行,当我传递指定的cron表达式时,它抛出NumberFormatException。

作为一种解决方法,我将为所有日期安排执行

0 10 10 * * ?
并检查计划方法中的实际日期

public void scheduledTask() {
    Calendar c = Calendar.getInstance();
    if (c.get(Calendar.DATE) == c.getActualMaximum(Calendar.DATE)) {
        ...
    }
}
此功能不在系统中。所以Spring可能永远不会实现它。查看,我看不到任何外科手术解决方案扩展
CronSequenceGenerator
。既然石英是一种特殊材料,为什么不使用它呢

根据您的具体需要,您可以实现自己的。比如:

import java.util.Date;

import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;

public class LastDayOfMonthTrigger implements Trigger {

    private final LocalTime time;

    public LastDayOfMonthTrigger(LocalTime time) {
        this.time = time;
    }

    @Override
    public Date nextExecutionTime(TriggerContext ctx) {
        Date last = ctx.lastScheduledExecutionTime();
        LocalDate date = last == null ? new LocalDate() : new LocalDate(last).plusDays(1);
        LocalDate lastDay = date.dayOfMonth().withMaximumValue();
        return lastDay.toDateTime(time).toDate();
    }
}

仅在每月最后一天运行的优化版本:

@Scheduled(cron = "0 55 23 28-31 * ?")
public void doStuffOnLastDayOfMonth() {
    final Calendar c = Calendar.getInstance();
    if (c.get(Calendar.DATE) == c.getActualMaximum(Calendar.DATE)) {
        // do your stuff
    }
}

还有另一个解决方案:

生成一个月的数据。该程序应在下个月的第一天运行,以确保捕获整个月的所有数据

import org.apache.commons.lang3.time.DateUtils;

@Scheduled(cron = "0 0 0 1 * ?") // runs on the first day of each month

public void doStuffOnFirstDayOfMonth() {

    Date now = DateUtils.addDays(new Date(), -1); // "now" is now on the last day of the month

}

我环顾了一下四周,似乎我真的得到了支持。你如何定义这份工作?注释?您可能应该将此添加到问题中。@Magnilex check UpdateGrat。您还可以粘贴调用
start()
方法的相关代码吗?对此我很抱歉,但我真的认为使用
L
应该可以工作。实际上,这不会影响输出,您可以在一个简单的主程序中测试它,只要在start方法中用“L”传递cron表达式,您就会得到异常。@Magnilex:我正在查看,我不明白为什么您认为它必须工作。它会工作,但是我只会把方法安排在一个月的最后几天,比如27-31天。是的,我认为这会是一些优化,但是你说你想要每个月的最后一天。对不起,我把自己放错了…“不仅仅是最后几天”..我想每月安排一次,一天可以是一个月的任何一天..但问题只出现在最后几天…即2月29日..而且我的cron表达式对于单个任务是动态的。检查更新..谢谢,我不能使用quartz,因为它需要架构级重构..“他们会杀了我”..我会试试你的想法它似乎会奏效。。。