如何正确访问/读取ItemReader/StaxEventItemReader中的对象?
根因分析
你直接调用read()方法抛空指针的核心原因是Spring Batch的ItemReader实现类大多带有生命周期管理,StaxEventItemReader实现了ItemStream接口,需要先完成初始化、打开底层资源(比如你指定的XML文件输入流、解析器上下文)之后才能正常读取数据,你直接调用read()时相关资源还没初始化,自然会报错。另外你贴的Bean定义里还有一个小问题:实例化时写的是new StaxEventItemReader<Obj>(),泛型和方法声明的StaxEventItemReader<Flight>不一致,建议先修正这个问题。
场景1:在Spring Batch作业流程内部访问读到的Flight对象
这是绝大多数场景的需求,推荐以下两种实现方式:
- 方案1:使用
ItemProcessor/ItemWriter直接获取
批处理的标准流程就是ItemReader读取单条数据 -> 传给ItemProcessor处理 -> 传给ItemWriter持久化,你如果需要对读到的Flight对象做操作,直接在你配置的Processor或者Writer组件里直接处理入参即可,这是最符合Spring Batch设计规范的用法,不需要额外修改Reader逻辑。 - 方案2:使用读取监听器
ItemReadListener获取
如果你不想修改原有Processor、Writer的逻辑,可以给Step添加ItemReadListener监听器,实现afterRead(Flight item)方法,每读完一条Flight数据该方法就会被触发,你可以在这个方法里完成你需要的操作,不会侵入原有业务流程。
场景2:在Spring Batch作业外部单独调用Reader读取数据
如果你确实需要脱离批处理作业,直接用这个Reader读取XML里的Flight数据,需要手动触发Reader的生命周期管理,示例代码如下:
@Autowired private StaxEventItemReader<Flight> flightReader; public void readFlightsDirectly() throws Exception { // 初始化Reader,打开底层资源 flightReader.open(new ExecutionContext()); Flight flight; // 循环读取,返回null代表读取完毕 while ((flight = flightReader.read()) != null) { // 此处可对获取到的flight对象做自定义操作 System.out.println(flight.getFlightNumber()); } // 读取完毕后关闭资源 flightReader.close(); }
注意:如果是在作业运行过程中不要手动调用Reader的read方法,ItemReader是有状态的,手动调用会移动读取指针,导致作业正常流程出现跳数据的问题。
内容的提问来源于stack exchange,提问作者Tom Steger
相关产品推荐
相关产品推荐

