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

Spring Boot读取实时更新JSON文件并同步至数据库问题求助

问题解决:Spring Boot定时读取更新后的JSON文件并同步到数据库

核心问题分析

  1. 读取旧数据的原因:getResourceAsStream()读取的是类加载器缓存的资源内容,而非实时的文件系统文件。当你更新resources/json/file.json时,类加载器不会自动刷新缓存,因此始终读取启动时的旧数据。
  2. MasterService为null的原因:手动new的类(如MyRunner)不属于Spring容器管理的Bean,Spring无法自动注入依赖,导致masterService为空。

解决方案

1. 修改文件读取逻辑,读取实时文件系统内容

替换getResourceAsStream()为直接读取文件系统的文件,推荐两种方式:

方式1:读取类路径下的文件(开发环境适用)

使用ClassPathResource获取实际文件路径,适用于本地开发环境:

@Autowired
private ResourceLoader resourceLoader;

@Scheduled(fixedRate=90000)
public void readFile() {
    ObjectMapper mapper = new ObjectMapper();
    TypeReference<List<Master>> typeReference = new TypeReference<List<Master>>(){};

    try {
        ClassPathResource resource = new ClassPathResource("json/file.json");
        File file = resource.getFile();
        List<Master> users = mapper.readValue(file, typeReference);
        
        System.out.println("users "+users);
        masterService.save(users);
        System.out.println("Saved");

    } catch (IOException e){
        System.out.println("Unable to save users: " + e.getMessage());
        e.printStackTrace();
    }
}

方式2:使用外部文件路径(推荐,适配生产环境)

将JSON文件写入外部目录而非resources下(jar包内部资源无法修改),配置固定外部路径:

@Scheduled(fixedRate=90000)
public void readFile() {
    ObjectMapper mapper = new ObjectMapper();
    TypeReference<List<Master>> typeReference = new TypeReference<List<Master>>(){};

    try {
        // 外部文件路径,可配置在application.properties中
        File file = new File("./data/json/file.json");
        // 确保父目录存在,避免文件写入失败
        file.getParentFile().mkdirs();
        
        List<Master> users = mapper.readValue(file, typeReference);
        
        System.out.println("users "+users);
        masterService.save(users);
        System.out.println("Saved");

    } catch (IOException e){
        System.out.println("Unable to save users: " + e.getMessage());
        e.printStackTrace();
    }
}

2. 解决依赖注入为null的问题

确保需要注入依赖的类由Spring容器管理,不要手动new:

步骤1:给自定义类添加Spring注解

比如MyRunner类添加@Component,让Spring扫描并管理:

@Component
public class MyRunner {
    private final MasterService masterService;

    // 构造注入,Spring自动注入依赖
    public MyRunner(MasterService masterService) {
        this.masterService = masterService;
    }

    public void runTask() {
        // 这里可以安全调用masterService的方法
    }
}

步骤2:通过Spring容器获取Bean

在主应用类中,不要手动new MyRunner,而是从Spring上下文获取:

@SpringBootApplication
@EnableScheduling
@EnableTransactionManagement
public class ReadAndWriteJsonApplication {
    @Autowired
    private MasterService masterService;
    @Autowired
    private MyRunner myRunner;

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(ReadAndWriteJsonApplication.class, args);
        // 从上下文获取Bean
        MyRunner myRunner = context.getBean(MyRunner.class);
        myRunner.runTask();
    }

    // 或者使用@PostConstruct在应用启动后执行
    @PostConstruct
    public void init() {
        myRunner.runTask();
    }

    // ... 定时任务方法
}

3. 优化依赖注入规范

MasterService中同时使用了字段注入和构造注入,建议统一使用构造注入(更安全、符合Spring规范):

@Service
public class MasterService {
    private final MasterRepository masterRepository;

    // 构造注入,Spring 4.3+无需添加@Autowired
    public MasterService(MasterRepository masterRepository) {
        this.masterRepository = masterRepository;
    }

    public Iterable<Master> list() {
        return masterRepository.findAll();
    }

    public Master save(Master master){
        return masterRepository.save(master);
    }

    public Iterable<Master> save(List<Master> masters) {
        return masterRepository.saveAll(masters);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 14:40:15