java batchjob_Spring Batch 3 - Job异常处理

上篇文章中,我们了解了读文件写数据库的流程。这里我们假设,日志文件在某一行的数据异常,比如逗号分隔后不是5部分,而变成了6部分,当程序执行到此行时就会抛出 FlatFileParseException 异常,Job停止执行。我们可以从两部分解决这个问题如果我们想让程序忽略这种异常,可以修改Job的配置方式如下:。

忽略异常

有些情况下,我们想让程序忽略掉这种异常,修改Job配置如下:

skip-limit="2000" 指可以忽略的最大次数(行数),如果你不知道你有都少个异常数据,想全部忽略掉,就尽量配置的大点

Job重新执行

另外的情况,出错时让程序停止,通过手工或其它方式纠正错误后,让程序继续执行。当然,比如我们处理到2051行错误时,纠正错误数据后,我们希望Job能继续从上次失败的行继续开始处理,而不是从第1行从头再来。 这就是Spring Batch的优势,它会自动记录你上次执行成功的地址,再次执行此job时会从这里继续出来。

我们来实际模拟下,假设我们在2051行的数据为:

2016-11-18 13:31:53,/test/user/user_visit/saveVisitStep,gz_qinrong,3,/test/3.201610171_1/Android,/5.1.1/Mi-4c/4faccbe5-bb26-4a0c-94aa-d9e0805f6367

注意在Android后面多加了一个逗号,导致此行逗号分隔后有6部分,而不是正常的5部分

执行job时我们会发生如下异常:

org.springframework.batch.item.file.FlatFileParseException: Parsing error at line: 2051 in resource=[URL [file:/my/access.log]], input=[2016-11-18 13:31:53,/test/user/user_visit/saveVisitStep,gz_qinrong,3,/test/3.201610171_1/Android,/5.1.1/Mi-4c/4faccbe5-bb26-4a0c-94aa-d9e0805f6367]

at org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:183)

at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:88)

at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:91)

at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:157)

at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:116)

at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:374)

at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)

at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)

at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:110)

at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:69)

at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406)

at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330)

at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)

at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:271)

at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:81)

at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:374)

at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)

at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)

at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:257)

at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:200)

at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)

at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)

at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67)

at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169)

at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144)

at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:134)

at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:306)

at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135)

at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)

at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128)

at com.me.springbatch.App.run(App.java:27)

at com.me.springbatch.file2db.File2DBMain.main(File2DBMain.java:9)

Caused by: org.springframework.batch.item.file.transform.IncorrectTokenCountException: Incorrect number of tokens found in record: expected 5 actual 6

at org.springframework.batch.item.file.transform.AbstractLineTokenizer.tokenize(AbstractLineTokenizer.java:125)

at org.springframework.batch.item.file.mapping.DefaultLineMapper.mapLine(DefaultLineMapper.java:43)

at org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:180)

... 31 more

Spring Batch 表BATCH_STEP_EXECUTION中的信息如下:

d63f96a52bf9

BATCH_STEP_EXECUTION表

从图上可以看出,程序读了2050行,写了2000行,提交了2次(我们设定了commit-interval="1000")。

如果我们不处理异常数据(错误依旧存在),再次执行下Job,肯定依旧程序会报异常,表BATCH_STEP_EXECUTION中的信息如下

d63f96a52bf9

BATCH_STEP_EXECUTION表

从表中可以看出。第二行读到50就异常了,写了0行,也就证明了Job是从上次成功的地方(2000行)后开始执行的。

我们手工纠正2051行的数据,去掉多余的逗号,再次执行,直到Job完全执行成功。

d63f96a52bf9

日志源文件总共508828行

d63f96a52bf9

BATCH_STEP_EXECUTION表

d63f96a52bf9

业务表

我们可以看到,业务表中的总数据量正好=多次执行的write_count合计。日志文件中的数据被完全处理,且未有重复数据。

总结

执行时要把spring-context.xml中的以下配置注释掉,否则每次执行都重新drop并创建表,也就无法保留上次执行的job信息了。

两次执行Job时,JobParameters参数必须要一样,否则Spring Batch会认为两次执行的为不同Job。

从这里我们就能看出Spring Batch的灵活与强大,后面的章节我们再看看Spring Batch还有哪些优点

附完整代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值