Spring Boot使用@Scheduler实现指定日期区间每分钟调用REST API存库
实现方案
1. 配置可读写的起止时间参数
先把自定义的起止时间加到配置类中,支持通过配置文件/配置中心修改,无需硬编码重启服务:
// 原有AppProperties配置类中新增字段 @ConfigurationProperties(prefix = "app") public class AppProperties { // 原有其他配置省略 private Date jobStartDate; private Date jobEndDate; // get、set方法省略 }
对应在application.yml中增加配置:
app: job-start-date: 2024-01-01 00:00:00 job-end-date: 2024-12-31 23:59:59
2. 调整定时任务的执行判断逻辑
保持@Scheduled每分钟触发的规则,在任务执行入口增加时间区间校验,不在范围内直接跳过执行,不发起API请求:
@Scheduled(cron = "0 * * * * ?") // 每分钟0秒触发 public void syncApiDataJob() { Date now = new Date(); // 不在配置的起止时间范围内直接终止当前次执行 if (now.before(appProperties.getJobStartDate()) || now.after(appProperties.getJobEndDate())) { return; } // 原有API调用、落库逻辑 Optional<String> uri = buidURL(now); if (uri.isEmpty()) { return; } String url = uri.get(); ResponseEntity<String> feedResponse = restTemplate.exchange(url, HttpMethod.GET, getRequest(headers()), String.class); // 后续数据解析、保存到数据库逻辑省略 }
3. 改造URL构建方法,支持参数化传入查询日期
原方法固定取当前日期前一天,修改为入参传入查询日期,适配不同时间点的查询需求:
// 入参增加目标查询日期 private Optional<String> buidURL(Date queryDate) { TimeZone timeZone = TimeZone.getTimeZone(Constants.TIME_ZONE); java.text.SimpleDateFormat format = new java.text.SimpleDateFormat(Constants.DATE_FORMAT); format.setTimeZone(timeZone); String jpQueryReqParam = appProperties.getRest().getReqParam(); String jpQuery = appProperties.getRest().getUri(); Optional<String> feed = Optional.empty(); try { feed = Optional.of(jpQuery + URLEncoder.encode(jpQueryReqParam.replace("$queryTimestamp", format.format(queryDate)), StandardCharsets.UTF_8.toString())); } catch (Exception e) { logger.info("Error occured at buidURL() " + e); } return feed; }
4. 补充历史区间数据补跑逻辑(可选)
如果需要补跑指定历史时间段的所有分钟数据,可以单独实现遍历方法,无需等待定时任务触发:
// 入参为需要补跑的起止时间 public void backfillHistoryData(Date startDate, Date endDate) { Calendar calendar = Calendar.getInstance(); calendar.setTime(startDate); // 遍历区间内的每一分钟 while (calendar.getTime().before(endDate)) { Date currentMinute = calendar.getTime(); Optional<String> uri = buidURL(currentMinute); if (uri.isPresent()) { String url = uri.get(); ResponseEntity<String> feedResponse = restTemplate.exchange(url, HttpMethod.GET, getRequest(headers()), String.class); // 数据解析、保存到数据库逻辑省略 } // 每次步进1分钟 calendar.add(Calendar.MINUTE, 1); } }
优化提示
SimpleDateFormat是线程不安全的,Java8及以上版本建议替换为DateTimeFormatter实现,避免多线程场景下的时间格式化异常- 如果需要动态调整起止时间无需重启服务,可以把起止时间配置放到配置中心,或者存储在数据库中,每次任务执行前读取最新配置
内容的提问来源于stack exchange,提问作者ASR
相关产品推荐
相关产品推荐

