`
feir8510
  • 浏览: 3933 次
社区版块
存档分类
最新评论

Spring batch自定义LineMapper实现特殊文本的处理

阅读更多

spring-batch是Java Spring的的批处理框架,而且提供了简单的文本处理功能。

下面的的例子,实现了对文本的下载和处理的流程。

 

<!-- Tasks分多个Task,Task启动job,job分为step -->
	<batch:job id="wxJob" job-repository="jobRepository" restartable="true" >
    	<batch:step id="downloadWxFile" next="analyseInfo">
    		<batch:tasklet>
    			<bean class="com.secondgame.demo_service.demo.batch.task.WxDownloadStep" scope="step">
    				<property name="filenamePrefix" value="#{jobParameters['filenamePrefix']}"></property>
    				<property name="date" value="#{jobParameters['date']}"></property>
    				<property name="datetime" value="#{jobParameters['datetime']}"></property>
    				<property name="workpath" value="#{jobParameters['workpath']}"></property>
    				<property name="filename" value="#{jobParameters['filename']}"></property>
    			</bean>
    		</batch:tasklet>
    	</batch:step>
    	<batch:step id="analyseInfo">
    		<!-- <bean class="com.secondgame.demo_service.demo.batch.task.depositor.LoadStep" scope="step">
    		</bean> -->
	    	<batch:tasklet transaction-manager="transactionManager">
	    		<batch:chunk reader="wxReader" writer="wxWriter" commit-interval="10">
	    		</batch:chunk>
    		</batch:tasklet>
    	</batch:step>
    </batch:job>
    
    <!-- wx Detail -->
    <bean id="wxReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
    	<property name="resource" value="file:#{jobParameters['filename']}"></property>
    	<property name="encoding" value="UTF-8"></property>
    	<property name="comments" value="#{'总'}"></property>
    	<property name="lineMapper" ref="wxMapper"></property>    
    	<property name="linesToSkip" value="1"></property>	    	
    </bean>
    <bean id="wxWriter" class="com.secondgame.demo_service.demo.batch.task.WxWriter" scope="step">
    		
    </bean>
    <bean id="wxMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper"> 
    <!-- <bean id="wxMapper" class="com.secondgame.demo_service.demo.batch.task.MyLineMapper"> -->

 

 

    	<property name="lineTokenizer" ref="wxMultiTokenizer"></property>
    	<property name="fieldSetMapper">
    		<bean class="com.secondgame.demo_service.demo.batch.task.WxFileSetMapper">
    		</bean>
    	</property>
    </bean>
    <bean id="wxMultiTokenizer" class="org.springframework.batch.item.file.transform.PatternMatchingCompositeLineTokenizer" scope="step">
    	<!-- <property name="delimiter" value=","></property> -->
   		<property name="tokenizers">
   			<map>
   				<entry key="*,*,*,*,*" value-ref="wxTokenizerTail"></entry>
   				<entry key="*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*" value-ref="wxTokenizer"></entry>
   			</map>
   		</property>
   	</bean>
    <bean id="wxTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer" scope="step">
     	<property name="delimiter" value=","></property>
    	<property name="names">
	   		<list>
	   			<value>tradeTime</value>
	   			<value>pubAccountId</value>
	   			<value>merchantId</value>
	   			<value>subMerchantId</value>
	   			<value>deviceId</value>
	   			<value>wxOrderId</value>
	   			<value>merchantOrderId</value>
	   			<value>userTag</value>
	   			<value>tradeType</value>
	   			<value>tradeStatus</value>
	   			<value>payerBank</value>
	   			<value>capitalType</value>
	   			<value>totalAmount</value>
	   			<value>enterpriseRedAmount</value>
	   			<value>wxRefundId</value>
	   			<value>merchantRefundId</value>
	   			<value>refundAmount</value>
	   			<value>enterpriseRedRefundAmount</value>
	   			<value>refundType</value>
	   			<value>refundStatus</value>
	   			<value>goodsName</value>
	   			<value>merchantData</value>
	   			<value>fee</value>
	   			<value>feeRate</value>
	   		</list>
    	</property>
    </bean>
    <bean id="wxTokenizerTail" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer" scope="step">
     	<property name="delimiter" value=","></property>
     	<property name="names">
	   		<list>
	   			<value>totalCount</value>
	   			<value>totalAmount</value>
	   			<value>refundAmount</value>
	   			<value>enterpriseRedRefundAmount</value>
	   			<value>fee</value>
	   		</list>
    	</property>
    </bean>

 可以看出,DefaultLineMapper实现了简单的文本处理功能,直接将切分的工作交给了wxMultiTokenizer处理文本的工作交给了WxFileSetMapper。这两个分别由两个bean实现注入,spring类DefaultLineMapper的代码如下:

 

package org.springframework.batch.item.file.mapping;
 
import org.springframework.batch.item.file.LineMapper;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.batch.item.file.transform.LineTokenizer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
 
/**
 * Two-phase {@link LineMapper} implementation consisting of tokenization of the line into {@link FieldSet} followed by
 * mapping to item. If finer grained control of exceptions is needed, the {@link LineMapper} interface should be
 * implemented directly.
 * 
 * @author Robert Kasanicky
 * @author Lucas Ward
 * 
 * @param <T> type of the item
 */
public class DefaultLineMapper<T> implements LineMapper<T>, InitializingBean {
 
    private LineTokenizer tokenizer;
 
    private FieldSetMapper<T> fieldSetMapper;
 
    @Override
    public T mapLine(String line, int lineNumber) throws Exception {
        return fieldSetMapper.mapFieldSet(tokenizer.tokenize(line));
    }
 
    public void setLineTokenizer(LineTokenizer tokenizer) {
        this.tokenizer = tokenizer;
    }
 
    public void setFieldSetMapper(FieldSetMapper<T> fieldSetMapper) {
        this.fieldSetMapper = fieldSetMapper;
    }
 
    @Override
    public void afterPropertiesSet() {
        Assert.notNull(tokenizer, "The LineTokenizer must be set");
        Assert.notNull(fieldSetMapper, "The FieldSetMapper must be set");
    }
}
 

核心方法mapLine就一句话:return fieldSetMapper.mapFieldSet(tokenizer.tokenize(line));

tokenizer解析后的结果,直接交给fieldSetMapper的mapFieldSet处理,用户仅需要自定义mapFieldSet方法实现如何处理。如何解析和如何处理不是本文关心的内容,后续笔者会专门介绍。

在这里有一个问题,如果文本有空行,tokenizer.tokenize(line)会返回""而不是null,导致fieldSetMapper.mapFieldSet抛异常,而FlatFileItemReader提供的方法又无法跳过空行(暂时还没有找到办法),在这里笔者仅做了一个简单的改造,实现了自己的LineMapper,代码如下:

package com.secondgame.demo_service.demo.batch.task;

import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.LineMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.LineTokenizer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

import com.alibaba.dubbo.common.utils.StringUtils;

public class MyLineMapper<T> implements LineMapper<T>, InitializingBean {
 
    private LineTokenizer tokenizer;
 
    private FieldSetMapper<T> fieldSetMapper;
 
    @Override
    public T mapLine(String line, int lineNumber) throws Exception {
    	if(StringUtils.isNotEmpty(line)){
    		return fieldSetMapper.mapFieldSet(tokenizer.tokenize(line));
    	}else{
    		return null;
    	}
    }
 
    public void setLineTokenizer(LineTokenizer tokenizer) {
        this.tokenizer = tokenizer;
    }
 
    public void setFieldSetMapper(FieldSetMapper<T> fieldSetMapper) {
        this.fieldSetMapper = fieldSetMapper;
    }
 
    @Override
    public void afterPropertiesSet() {
        Assert.notNull(tokenizer, "The LineTokenizer must be set");
        Assert.notNull(fieldSetMapper, "The FieldSetMapper must be set");
    }
}

总体代码都一样,只是在方法mapLine中对空串进行特别处理即可。框架对null的返回不作处理。

当然xml中,仍需修改一行代码,引用自定义的mapper即可

<!--<bean id="wxMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper">--> 
   <bean id="wxMapper" class="com.secondgame.demo_service.demo.batch.task.MyLineMapper">

 写了半天,就是两句话的事儿:

 1. 模仿重写DefaultLineMapper的mapLine方法适配空行

 2. 配置文件使用自定义的MyLineMapper方法

 3. 其它的更复杂的需求也可以用这个方法:比如过滤含有某些特殊字符的行(非行首),对特别文本进行替换(A替换成B)等等,都可以在这里进行行级别的处理

 

 

 

 

分享到:
评论

相关推荐

    基于Spring Batch的大数据量并行处理

    - **高性能与可扩展性**:Spring Batch支持高并发处理,可以通过简单的配置实现应用的纵向和横向扩展。 - **丰富的特性**:包括但不限于事务管理、重试机制、跳过机制、作业监控等。 - **全面的API支持**:提供了...

    Spring Boot整合Spring Batch,实现批处理

    Spring Boot以其简洁的配置和快速的启动能力深受开发者喜爱,而Spring Batch作为Spring框架的一部分,专注于批量处理任务,提供了强大的数据处理能力和事务管理功能。下面我们将深入探讨这个主题。 首先,**Spring ...

    quartz整合springbatch动态集群定时实现mysql参考

    Quartz主要用于任务调度,而Spring Batch则专注于批量处理。在这个“quartz_springbatch_dynamic”项目中,我们将看到如何将这两个强大的工具结合起来,以实现动态集群环境中的定时任务执行,并使用MySQL作为数据...

    spring Batch实现数据库大数据量读写

    Spring Batch 是一个强大的、可扩展的Java框架,专门用于处理批量数据处理任务,包括大量数据库数据的读取、处理和写入。它被设计为在企业级应用中处理大规模、高吞吐量的工作负载。本篇文章将深入探讨如何利用...

    SpringBatch+Spring+Mybatis+MySql (spring batch 使用jar)

    Spring Batch是一个轻量级的,完全面向Spring的批处理框架,可以应用于企业级大量的数据处理系统。Spring Batch以POJO和大家熟知的Spring框架为基础,使开发者更容易的访问和利用企业级服务。Spring Batch可以提供...

    Spring Batch in Action英文pdf版

    Spring Batch中的数据处理是通过Processor接口来实现的。Processor接口允许开发者在数据写入之前对其进行转换、验证或其他业务逻辑处理。Spring Batch还提供了丰富的批处理统计信息和监听器,以监控和控制数据处理...

    spring-batch分区处理示例

    Spring Batch 是一个强大的Java框架,专门用于处理批量数据处理任务。在Spring Batch中,分区处理是一种优化策略,它将大型工作负载分解成多个较小、独立的任务,这些任务可以在不同的线程或甚至不同的节点上并行...

    springBatch 组件学习教程源码

    Spring Batch 是一个强大的、全面的批处理...同时,你也可以探索如何将 Spring Batch 整合到现有的 Spring 应用程序中,以实现高效的数据处理功能。记得在实践中不断尝试和优化,以便更好地掌握这个强大的批处理框架。

    quartz整合springbatch定时集群实现mysql参考模版

    Quartz和SpringBatch是两种在Java开发中广泛使用的框架,Quartz用于任务调度,而SpringBatch则用于批量处理。在大型分布式系统中,结合这两者可以实现强大的定时任务集群功能,尤其是在需要对大量数据进行定时处理的...

    springbatch 详解PDF附加 全书源码 压缩包

    Spring Batch 是一个强大的、全面的批处理框架,由 Spring 社区开发,旨在简化企业级应用中的批量数据处理任务。这个框架提供了一种标准的方式来处理大量的数据输入和输出,使得开发者能够专注于业务逻辑,而不是...

    springBoot+springBatch批量处理数据demo

    在这个“springBoot+springBatch批量处理数据demo”中,我们将探讨如何将这两个强大的工具结合在一起,实现高效的数据处理。 首先,SpringBoot的核心特性在于其自动配置,它通过`@SpringBootApplication`注解自动...

    spring-batch包

    Spring Batch 是一个强大的、全面的批处理框架,用于处理大量数据的处理任务。它由 Spring 框架提供支持,因此具有高度的可配置性和可扩展性,适用于各种企业级应用。Spring Batch 4.0.0 版本是该框架的一个重要版本...

    Spring Batch批处理框架

    Spring Batch提供了强大的错误处理机制,比如可以配置当ItemReader读取失败时,作业会自动重试,或当ItemProcessor处理出错时,可以跳过当前项继续处理下一项。这些机制极大地提高了批处理作业的健壮性。 5. 作业...

    Spring Batch读取txt文件并写入数据库的方法教程

    在本教程中,我们将探讨如何使用 Spring Batch 读取文本(txt)文件,并将读取到的数据处理后写入数据库。 首先,我们需要创建一个 Maven 项目,并在 `pom.xml` 文件中添加必要的依赖。这些依赖包括 `spring-boot-...

    Spring batch in action

    本书的第二部分深入探讨了Spring Batch的核心概念,包括如何配置批处理作业、运行作业、读取和写入数据、处理数据以及实现可靠的作业。第三部分进一步深入到高级话题,涵盖执行处理、企业集成、监控、扩展以及批量...

    pro spring batch 源码

    - RemoteChunking 和 GridSphere 框架可以实现 Spring Batch 的分布式处理。 通过阅读 "Pro Spring Batch" 源码,你可以了解到这些组件如何协同工作,以及如何根据项目需求进行定制和扩展。这将使你具备设计和实施...

    springbatch简单用

    SpringBatch 是一个强大的、全面的批处理框架,用于处理大量数据。它被设计为高度可扩展和模块化,适用于各种企业级应用。SpringBatch 提供了处理批量作业所需的全部基础设施,包括读取、处理和写入数据,以及作业...

    Spring Batch学习demo项目源码

    例如,`ItemProcessor`接口用于实现自定义的处理逻辑。 5. **写入器(Writer)**:数据处理后,`ItemWriter`将结果写入目标,如文件、数据库等。 6. **事务管理**:Spring Batch 自动处理事务边界,确保批处理操作...

    springbatch mybatis 代码

    1. **读/写操作**:Spring Batch 提供了多种ItemReader和ItemWriter接口,如JdbcPagingItemReader用于分页读取数据库数据,FlatFileItemWriter用于将数据写入文本文件等。 2. **事务管理**:Spring Batch 自动处理...

    The Definitive Guide to Spring Batch, 2nd Edition.epub

    Work with all aspects of batch processing in a modern Java environment using a selection of Spring frameworks. This book provides up-to-date examples using the latest configuration techniques based on...

Global site tag (gtag.js) - Google Analytics