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

如何使用Spring Batch的Item Reader完成汇率文件垂直映射读取

答案

完全可以实现,Spring Batch支持自定义ItemReader逻辑适配这种特殊结构的汇率文件。

实现思路

因为文件仅包含2行内容(第一行货币标识、第二行对应汇率),默认逐行映射为单个业务对象的FlatFileItemReader不能直接满足需求,我们可以自定义ItemReader实现读取+配对逻辑,全程适配动态列数的扩展需求,后续新增货币不需要修改读取层代码。

具体实现步骤

1. 定义业务实体类

先创建存储货币汇率的实体类:

import java.math.BigDecimal;

public class CurrencyRate {
    // 货币标识
    private String currencyCode;
    // 对应汇率
    private BigDecimal rate;

    // 此处省略getter、setter方法
}

2. 自定义ItemReader实现

自定义Reader一次性加载文件的两行内容,完成货币与汇率的配对,再逐个返回实体对象:

import org.springframework.batch.item.ItemReader;
import org.springframework.core.io.Resource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CurrencyRateItemReader implements ItemReader<CurrencyRate> {
    // 存储配对完成的汇率列表
    private List<CurrencyRate> currencyRateList;
    // 读取游标
    private int cursor = 0;

    public CurrencyRateItemReader(Resource rateFile) {
        this.currencyRateList = loadAndMapRateFile(rateFile);
    }

    private List<CurrencyRate> loadAndMapRateFile(Resource rateFile) {
        List<CurrencyRate> resultList = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(rateFile.getInputStream()))) {
            // 读取第一行货币标识
            String currencyLine = br.readLine();
            if (currencyLine == null || currencyLine.isBlank()) {
                return resultList;
            }
            List<String> currencyCodeList = Arrays.stream(currencyLine.split(","))
                    .map(String::trim)
                    .toList();
            // 读取第二行汇率数值
            String rateLine = br.readLine();
            if (rateLine == null || rateLine.isBlank()) {
                return resultList;
            }
            List<String> rateStrList = Arrays.stream(rateLine.split(","))
                    .map(String::trim)
                    .toList();
            // 按索引配对,超出最小长度的异常列自动忽略
            int validSize = Math.min(currencyCodeList.size(), rateStrList.size());
            for (int i = 0; i < validSize; i++) {
                CurrencyRate rate = new CurrencyRate();
                rate.setCurrencyCode(currencyCodeList.get(i));
                rate.setRate(new BigDecimal(rateStrList.get(i)));
                resultList.add(rate);
            }
        } catch (Exception e) {
            throw new RuntimeException("汇率文件读取失败", e);
        }
        return resultList;
    }

    @Override
    public CurrencyRate read() {
        // 游标遍历完成后返回null通知Spring Batch读取结束
        if (cursor < currencyRateList.size()) {
            return currencyRateList.get(cursor++);
        }
        return null;
    }
}

3. 注册到Spring Batch上下文

在Batch配置类中注入自定义Reader即可,后续可以和常规Reader一样对接处理器、写入器使用:

import org.springframework.batch.item.ItemReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;

@Configuration
public class BatchConfig {

    @Bean
    public ItemReader<CurrencyRate> currencyRateItemReader(
            // 替换为你的汇率文件实际路径
            @Value("${rate.file.path:classpath:exchange_rate.csv}") Resource rateFile
    ) {
        return new CurrencyRateItemReader(rateFile);
    }
}

补充说明

如果不想完全自定义Reader,也可以扩展FlatFileItemReader,通过skippedLinesCallback先读取第一行的货币列表存到执行上下文中,再自定义LineMapper处理第二行的汇率值完成配对,不过自定义ItemReader的方式逻辑更直观,维护成本更低,也天然支持动态扩展的列数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 12:24:05