Spring Batch中如何避免将含;;;;;;的行传入ItemWriter?
解决Spring Batch中避免将含
;;;;;;的行传给ItemWriter的问题 看起来你遇到的问题是,那些包含;;;;;;的行虽然经过了Mapper和Processor处理,但还是有长度为0(空)的条目传到了ItemWriter的write()方法里。我来帮你梳理几个可行的解决思路:
1. 在ItemProcessor中严格过滤空模型对象
最直接的方式是在Processor里检查处理后的模型是否所有字段都为空,如果是就返回null——Spring Batch会自动跳过返回null的条目,不会传给Writer。
比如你可以给Processor加一个空对象判断的辅助方法:
private boolean isModelEmpty(YourModel model) { // 逐一检查模型的所有字段,判断是否都为空/空字符串/默认值 return (model.getFieldA() == null || model.getFieldA().isEmpty()) && (model.getFieldB() == null || model.getFieldB().isEmpty()) && // 继续检查其他所有字段 ; } @Override public YourModel process(YourModel item) throws Exception { // 你的原有处理逻辑... // 最后判断是否为空对象,是则返回null跳过 if (isModelEmpty(item)) { return null; } return item; }
注意要覆盖所有字段的判断,避免因为遗漏字段导致空对象漏网。
2. 在ItemReader阶段直接跳过无效行
如果不想让这些无效行进入后续的Mapper和Processor,可以在Reader层面就拦截掉包含;;;;;;的行。比如用自定义的LineMapper:
public class CustomValidatingLineMapper implements LineMapper<YourModel> { private DefaultLineTokenizer tokenizer; private BeanWrapperFieldSetMapper<YourModel> fieldSetMapper; @Override public YourModel mapLine(String line, int lineNumber) throws Exception { // 先检查行是否包含目标无效串,直接抛出SkipException让Batch跳过该行 if (line.contains(";;;;;;")) { throw new SkipException(String.format("跳过含无效分隔符的行:第%d行", lineNumber)); } FieldSet fieldSet = tokenizer.tokenize(line); // 再判断分割后的FieldSet是否为空 if (fieldSet == null || fieldSet.getFieldCount() == 0) { throw new SkipException(String.format("跳过空字段集的行:第%d行", lineNumber)); } return fieldSetMapper.mapFieldSet(fieldSet); } // 提供setter方法注入tokenizer和fieldSetMapper public void setTokenizer(DefaultLineTokenizer tokenizer) { this.tokenizer = tokenizer; } public void setFieldSetMapper(BeanWrapperFieldSetMapper<YourModel> fieldSetMapper) { this.fieldSetMapper = fieldSetMapper; } }
然后在Reader的配置中使用这个自定义LineMapper,同时记得配置SkipPolicy允许跳过SkipException:
@Bean public FlatFileItemReader<YourModel> itemReader() { FlatFileItemReader<YourModel> reader = new FlatFileItemReader<>(); // 配置文件路径、编码等... CustomValidatingLineMapper lineMapper = new CustomValidatingLineMapper(); lineMapper.setTokenizer(yourTokenizer()); lineMapper.setFieldSetMapper(yourFieldSetMapper()); reader.setLineMapper(lineMapper); // 配置跳过策略 reader.setSkippedRecordsCallback((line, lineNumber) -> log.warn("跳过无效行:第{}行,内容:{}", lineNumber, line)); reader.setSkipPolicy(new AlwaysSkipItemSkipPolicy()); return reader; }
3. 检查现有Processor的逻辑漏洞
如果已经有Processor处理,还是有空对象传到Writer,那大概率是Processor的过滤逻辑有遗漏。比如:
- 只判断了部分字段,没覆盖所有可能为空的字段;
- 判断条件写反了,或者逻辑运算符用错(比如把
&&写成了||); - 某些字段的默认值不是
null,比如是空字符串,但判断时只检查了null。
可以加日志打印一下进入Processor的对象,看看哪些空对象没被过滤,针对性调整判断逻辑。
内容的提问来源于stack exchange,提问作者M06H
相关产品推荐
相关产品推荐

