You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot:如何在用户输入数据后调用CommandLineRunner?

问题解答

首先明确:CommandLineRunner无法满足你的需求。它是Spring Boot专为应用启动阶段执行一次性初始化逻辑设计的组件,启动完成后不会再被触发,因此不可能在用户输入数据后调用它执行任务。

你的代码还存在两个核心问题:

  1. CovidConfig中的Controller和Date字段未做依赖注入,启动时必然触发空指针;
  2. 即使注入成功,启动阶段用户还未输入日期,date对象依然为空,同样会引发空指针异常。

正确实现方案

将原CommandLineRunner中的业务逻辑抽成独立服务类,在用户提交日期的POST接口中直接调用该服务,完成数据获取与入库操作。

步骤1:创建Covid数据处理服务类

把数据请求、解析、入库的逻辑封装到专门的服务类中:

package com.andrekreou.covid.gov.service;

import com.andrekreou.covid.gov.model.Covid;
import com.andrekreou.covid.gov.repository.CovidRepo;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Collections;
import java.util.List;

@Service
public class CovidDataService {

    private final CovidRepo covidRepo;
    private final RestTemplate restTemplate;

    public CovidDataService(CovidRepo covidRepo, RestTemplate restTemplate) {
        this.covidRepo = covidRepo;
        this.restTemplate = restTemplate;
    }

    public List<Covid> fetchAndSaveCovidData(String date) {
        // 生成目标请求URL
        String url = "https://data.gov.gr/api/v1/query/mdg_emvolio?date_from=" + date + "&date_to=" + date;

        // 构造请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        headers.set("Authorization","Token 8329eb4fa30e567d9e3f6bfed266c8cb4c9c94ad");

        HttpEntity<Object> request = new HttpEntity<>(headers);

        // 请求第三方API并解析返回结果
        ResponseEntity<List<Covid>> response = restTemplate.exchange(
                url,
                HttpMethod.GET,
                request,
                new ParameterizedTypeReference<List<Covid>>() {}
        );

        // 将数据保存到数据库
        List<Covid> covidList = response.getBody();
        if (covidList != null && !covidList.isEmpty()) {
            covidRepo.saveAll(covidList);
        }
        return covidList;
    }
}

步骤2:修改Controller的POST接口

用户提交日期后,直接调用服务类方法处理业务:

package com.andrekreou.covid.gov.controller;

import com.andrekreou.covid.gov.model.Covid;
import com.andrekreou.covid.gov.service.CovidDataService;
import com.andrekreou.covid.gov.service.Service;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;

@RestController
public class Controller {

    private final Service service;
    private final CovidDataService covidDataService;

    public Controller(Service service, CovidDataService covidDataService) {
        this.service = service;
        this.covidDataService = covidDataService;
    }

    @GetMapping(path = "/covid")
    public List<List<Covid>> getData(){
        return service.getData();
    }

    @PostMapping(value = "/insert/date")
    public ModelAndView insertDate(@RequestParam("date") @DateTimeFormat(pattern = "yyyy-MM-dd") String date) {
        // 调用服务类处理数据
        List<Covid> covidList = covidDataService.fetchAndSaveCovidData(date);
        
        // 返回结果页面(可根据需求调整为JSON响应或重定向)
        ModelAndView mav = new ModelAndView("result");
        mav.addObject("covidList", covidList);
        return mav;
    }
}

步骤3:简化配置类

移除原CommandLineRunner,仅保留RestTemplate的Bean配置(服务类依赖它发起HTTP请求):

package com.andrekreou.covid.gov.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class CovidConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

步骤4:优化日期输入验证

在Date类中添加日期格式注解,确保用户输入的日期格式符合要求:

package com.andrekreou.covid.gov.model;

import org.springframework.format.annotation.DateTimeFormat;

public class Date {
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private String date;

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }
}

额外建议

  1. 异常处理:给RestTemplate调用添加异常捕获逻辑,处理HttpClientErrorException、HttpServerErrorException等异常,返回友好的错误提示;
  2. 日志记录:在服务类中添加日志,记录数据请求和入库情况,方便排查问题;
  3. 定时执行需求:如果需要定期同步数据,可以使用Spring的@Scheduled注解,而非CommandLineRunner。

内容的提问来源于stack exchange,提问作者Alex_Pap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 19:10:47