Spring Batch输出文本数据 XML数据 JSON数据 数据库

简介: Spring Batch输出文本数据 XML数据 JSON数据 数据库

Spring Batch输出数据通过 ItemWriter接口的实现类来完成,包括 FlatFileItemWriter文本数据输出、 StaxEventItemWriter XML文件数据输出、 JsonItemWriter JSON文件数据输出、 JdbcBatchItemWriter数据库数据插入等实现,更多可用的实现可以参考: https://docs.spring.io/spring-batch/docs/4.2.x/reference/html/appendix.html#itemWritersAppendix,本文只介绍这四种比较常用的输出数据方式。


1. 框架搭建


新建一个Spring Boot项目,版本为2.2.4.RELEASE,artifactIdspring-batch-itemwriter


剩下的数据库层的准备,项目配置,依赖引入和Spring Batch入门文章中的框架搭建步骤一致.


在介绍Spring Batch数据输出之前,我们先准备个简单的数据读取源。在包下新建entity包,然后在该包下新建TestData实体类:

@Data // 生成get、set
public class TestData {
    private int id;
    private String field1;
    private String field2;
    private String field3;
}


接着新建reader包,然后在该包下创建ItemReaderConfigure

@Configuration
public class ItemReaderConfigure {
    @Bean
    public ListItemReader<TestData> simpleReader() {
        List<TestData> data = new ArrayList<>();
        TestData testData1 = new TestData();
        testData1.setId(1);
        testData1.setField1("11");
        testData1.setField2("12");
        testData1.setField3("13");
        data.add(testData1);
        TestData testData2 = new TestData();
        testData2.setId(2);
        testData2.setField1("21");
        testData2.setField2("22");
        testData2.setField3("23");
        data.add(testData2);
        return new ListItemReader<>(data);
    }
}


上面注册了一个ItemReader类型的Bean,后续都用它作为读取数据的来源。


2. 输出文本数据


新建job包,然后在该包下新建FileItemWriterDemo,用于测试Spring Batch输出数据到文本文件:

@Component
public class FileItemWriterDemo {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private ListItemReader<TestData> simpleReader;
    @Bean
    public Job fileItemWriterJob() throws Exception {
        return jobBuilderFactory.get("fileItemWriterJob")
                .start(step())
                .build();
    }
    private Step step() throws Exception {
        return stepBuilderFactory.get("step")
                .<TestData, TestData>chunk(2)
                .reader(simpleReader)
                .writer(fileItemWriter())
                .build();
    }
    private FlatFileItemWriter<TestData> fileItemWriter() throws Exception {
        FlatFileItemWriter<TestData> writer = new FlatFileItemWriter<>();
        FileSystemResource file = new FileSystemResource("E:\\file");
        Path path = Paths.get(file.getPath());
        if (!Files.exists(path)) {
            Files.createFile(path);
        }
        // 设置输出文件路径
        writer.setResource(file); 
        // 把读到的每个TestData对象转换为JSON字符串
        LineAggregator<TestData> aggregator = item -> {
            try {
                ObjectMapper mapper = new ObjectMapper();
                return mapper.writeValueAsString(item);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return "";
        };
        writer.setLineAggregator(aggregator);
        writer.afterPropertiesSet();
        return writer;
    }
}


上面代码中,Step中的Reader使用的是我们上面创建的simpleReader,文本数据输出使用的是FlatFileItemWriterfileItemWriter()方法的代码较为简单。


启动项目后,在E:\\目录下(也就是我的电脑桌面上)会多出个file文件:


3. 输出xml数据


同样的,xml格式数据输出需要借助spring-oxm框架,在pom中引入相关依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-oxm</artifactId>
</dependency>
<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.11.1</version>
</dependency>


然后在job包下新建XmlFileItemWriterDemo,用于测试Spring Batch输出数据到xml文件:

@Component
public class XmlFileItemWriterDemo {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private ListItemReader<TestData> simpleReader;
    @Bean
    public Job xmlFileItemWriterJob() throws Exception {
        return jobBuilderFactory.get("xmlFileItemWriterJob")
                .start(step())
                .build();
    }
    private Step step() throws Exception {
        return stepBuilderFactory.get("step")
                .<TestData, TestData>chunk(2)
                .reader(simpleReader)
                .writer(xmlFileItemWriter())
                .build();
    }
    private StaxEventItemWriter<TestData> xmlFileItemWriter() throws IOException {
        StaxEventItemWriter<TestData> writer = new StaxEventItemWriter<>();
        // 通过XStreamMarshaller将TestData转换为xml
        XStreamMarshaller marshaller = new XStreamMarshaller();
        Map<String,Class<TestData>> map = new HashMap<>(1);
        map.put("test", TestData.class);
        marshaller.setAliases(map); // 设置xml标签
        writer.setRootTagName("tests"); // 设置根标签
        writer.setMarshaller(marshaller);
        FileSystemResource file = new FileSystemResource("E:\\file.xml");
        Path path = Paths.get(file.getPath());
        if (!Files.exists(path)) {
            Files.createFile(path);
        }
        writer.setResource(file); // 设置目标文件路径
        return writer;
    }
}


xml类型文件输出使用的是StaxEventItemWriter


启动项目后,在E:\\目录下会多出个file.xml文件:


4. 输出JSON数据


在job包下新建JsonFileItemWriterDemo,用于测试Spring Batch输出数据到json文件:

@Component
public class JsonFileItemWriterDemo {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private ListItemReader<TestData> simpleReader;
    @Bean
    public Job jsonFileItemWriterJob() throws Exception {
        return jobBuilderFactory.get("jsonFileItemWriterJob")
                .start(step())
                .build();
    }
    private Step step() throws Exception {
        return stepBuilderFactory.get("step")
                .<TestData, TestData>chunk(2)
                .reader(simpleReader)
                .writer(jsonFileItemWriter())
                .build();
    }
    private JsonFileItemWriter<TestData> jsonFileItemWriter() throws IOException {
        // 文件输出目标地址
        FileSystemResource file = new FileSystemResource("E:\\file.json");
        Path path = Paths.get(file.getPath());
        if (!Files.exists(path)) {
            Files.createFile(path);
        }
        // 将对象转换为json
        JacksonJsonObjectMarshaller<TestData> marshaller = new JacksonJsonObjectMarshaller<>();
        JsonFileItemWriter<TestData> writer = new JsonFileItemWriter<>(file, marshaller);
        // 设置别名
        writer.setName("testDatasonFileItemWriter");
        return writer;
    }
}


启动项目后,在E:\\目录下会多出个file.json文件:


5. 输出数据到数据库


在job包下新建DatabaseItemWriterDemo,用于测试Spring Batch输出数据到数据库:

@Component
public class DatabaseItemWriterDemo {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private ListItemReader<TestData> simpleReader;
    @Autowired
    private DataSource dataSource;
    @Bean
    public Job datasourceItemWriterJob() {
        return jobBuilderFactory.get("datasourceItemWriterJob")
                .start(step())
                .build();
    }
    private Step step() {
        return stepBuilderFactory.get("step")
                .<TestData, TestData>chunk(2)
                .reader(simpleReader)
                .writer(dataSourceItemWriter())
                .build();
    }
    private ItemWriter<TestData> dataSourceItemWriter() {
        // ItemWriter的实现类之一,mysql数据库数据写入使用JdbcBatchItemWriter,
        // 其他实现:MongoItemWriter,Neo4jItemWriter等
        JdbcBatchItemWriter<TestData> writer = new JdbcBatchItemWriter<>();
        writer.setDataSource(dataSource); // 设置数据源
        String sql = "insert into TEST(id,field1,field2,field3) values (:id,:field1,:field2,:field3)";
        writer.setSql(sql); // 设置插入sql脚本
        // 映射TestData对象属性到占位符中的属性
        BeanPropertyItemSqlParameterSourceProvider<TestData> provider = new BeanPropertyItemSqlParameterSourceProvider<>();
        writer.setItemSqlParameterSourceProvider(provider);
        writer.afterPropertiesSet(); // 设置一些额外属性
        return writer;
    }
}


MySQL关系型数据数据写入使用的是JdbcBatchItemWriter。在测试之前,先清空springbatch数据库TEST表数据,然后启动项目,启动后,查看表中数据。


6. 多文本输出


多文本输出需要通过代理来完成。我们模拟个同时输出xml格式和普通文本格式的例子。


在项目里新建writer包,然后在该包下新建ItemWriterConfigure配置类:

@Configuration
public class ItemWriterConfigure {
    @Bean
    public FlatFileItemWriter<TestData> fileItemWriter() throws Exception {
        FlatFileItemWriter<TestData> writer = new FlatFileItemWriter<>();
        FileSystemResource file = new FileSystemResource("E:\\file1");
        Path path = Paths.get(file.getPath());
        if (!Files.exists(path)) {
            Files.createFile(path);
        }
        writer.setResource(file); // 设置目标文件路径
        // 把读到的每个TestData对象转换为字符串
        LineAggregator<TestData> aggregator = item -> {
            try {
                ObjectMapper mapper = new ObjectMapper();
                return mapper.writeValueAsString(item);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return "";
        };
        writer.setLineAggregator(aggregator);
        writer.afterPropertiesSet();
        return writer;
    }
    @Bean
    public StaxEventItemWriter<TestData> xmlFileItemWriter() throws Exception {
        StaxEventItemWriter<TestData> writer = new StaxEventItemWriter<>();
        // 通过XStreamMarshaller将TestData转换为xml
        XStreamMarshaller marshaller = new XStreamMarshaller();
        Map<String, Class<TestData>> map = new HashMap<>(1);
        map.put("test", TestData.class);
        marshaller.setAliases(map); // 设置xml标签
        writer.setRootTagName("tests"); // 设置根标签
        writer.setMarshaller(marshaller);
        FileSystemResource file = new FileSystemResource("E:\\file1.xml");
        Path path = Paths.get(file.getPath());
        if (!Files.exists(path)) {
            Files.createFile(path);
        }
        writer.setResource(file); // 设置目标文件路径
        return writer;
    }
}


上面的配置类中,配置了FlatFileItemWriterStaxEventItemWriter类型的ItemWriter Bean,代码步骤和前面介绍的一致。


然后在job包下新建MultiFileItemWriteDemo,用于测试多文本输出:

@Component
public class MultiFileItemWriteDemo {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private ListItemReader<TestData> simpleReader;
    @Autowired
    private ItemStreamWriter<TestData> fileItemWriter;
    @Autowired
    private ItemStreamWriter<TestData> xmlFileItemWriter;
    @Bean
    public Job multiFileItemWriterJob() {
        return jobBuilderFactory.get("multiFileItemWriterJob")
                .start(step())
                .build();
    }
    private Step step() {
        return stepBuilderFactory.get("step")
                .<TestData, TestData>chunk(2)
                .reader(simpleReader)
                .writer(classifierMultiFileItemWriter())
                .stream(fileItemWriter)
                .stream(xmlFileItemWriter)
                .build();
    }
    // 将数据分类,然后分别输出到对应的文件(此时需要将writer注册到ioc容器,否则报
    // WriterNotOpenException: Writer must be open before it can be written to)
    private ClassifierCompositeItemWriter<TestData> classifierMultiFileItemWriter() {
        ClassifierCompositeItemWriter<TestData> writer = new ClassifierCompositeItemWriter<>();
        writer.setClassifier((Classifier<TestData, ItemWriter<? super TestData>>) testData -> {
            try {
                // id能被2整除则输出到普通文本,否则输出到xml文本
                return testData.getId() % 2 == 0 ? fileItemWriter : xmlFileItemWriter;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        });
        return writer;
    }
}


ClassifierCompositeItemWriter可以设置不同条件下使用不同的ItemWriter输出数据,此外在Step中,还需通过StepBuilderFactorystream()方法传入使用到的ItemWriter(这里需要注意的是,注入的时候,类型应选择ItemStreamWriter)。


启动后就会发现,集合中的数据根据不同的条件输出到不同的文件中。


如果不想用分类,希望所有数据都输出到对应格式的文本中,则可以使用CompositeItemWriter作为代理输出,修改MultiFileItemWriteDemo

@Component
public class MultiFileItemWriteDemo {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private ListItemReader<TestData> simpleReader;
    @Autowired
    private ItemStreamWriter<TestData> fileItemWriter;
    @Autowired
    private ItemStreamWriter<TestData> xmlFileItemWriter;
    @Bean
    public Job multiFileItemWriterJob() {
        return jobBuilderFactory.get("multiFileItemWriterJob2")
                .start(step())
                .build();
    }
    private Step step() {
        return stepBuilderFactory.get("step")
                .<TestData, TestData>chunk(2)
                .reader(simpleReader)
                .writer(multiFileItemWriter())
                .build();
    }
    // 输出数据到多个文件
    private CompositeItemWriter<TestData> multiFileItemWriter() {
        // 使用CompositeItemWriter代理
        CompositeItemWriter<TestData> writer = new CompositeItemWriter<>();
        // 设置具体写代理
        writer.setDelegates(Arrays.asList(fileItemWriter, xmlFileItemWriter));
        return writer;
    }
}


在启动项目前,先删掉E:\\目录下的之前测试的文件。删掉后,启动项目。

目录
打赏
0
0
0
0
16
分享
相关文章
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
83 1
淘宝商品详情API的调用流程(python请求示例以及json数据示例返回参考)
JSON数据示例:需要提供一个结构化的示例,展示商品详情可能包含的字段,如商品标题、价格、库存、描述、图片链接、卖家信息等。考虑到稳定性,示例应基于淘宝开放平台的标准响应格式。
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
35 0
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——封装统一返回的数据结构
本文介绍了在Spring Boot中封装统一返回的数据结构的方法。通过定义一个泛型类`JsonResult&lt;T&gt;`,包含数据、状态码和提示信息三个属性,满足不同场景下的JSON返回需求。例如,无数据返回时可设置默认状态码&quot;0&quot;和消息&quot;操作成功!&quot;,有数据返回时也可自定义状态码和消息。同时,文章展示了如何在Controller中使用该结构,通过具体示例(如用户信息、列表和Map)说明其灵活性与便捷性。最后总结了Spring Boot中JSON数据返回的配置与实际项目中的应用技巧。
67 0
|
12天前
|
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——使用 fastJson 处理 null
本文介绍如何使用 fastJson 处理 null 值。与 Jackson 不同,fastJson 需要通过继承 `WebMvcConfigurationSupport` 类并覆盖 `configureMessageConverters` 方法来配置 null 值的处理方式。例如,可将 String 类型的 null 转为 &quot;&quot;,Number 类型的 null 转为 0,避免循环引用等。代码示例展示了具体实现步骤,包括引入相关依赖、设置序列化特性及解决中文乱码问题。
37 0
|
12天前
|
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——Spring Boot 默认对Json的处理
本文介绍了在Spring Boot中返回Json数据的方法及数据封装技巧。通过使用`@RestController`注解,可以轻松实现接口返回Json格式的数据,默认使用的Json解析框架是Jackson。文章详细讲解了如何处理不同数据类型(如类对象、List、Map)的Json转换,并提供了自定义配置以应对null值问题。此外,还对比了Jackson与阿里巴巴FastJson的特点,以及如何在项目中引入和配置FastJson,解决null值转换和中文乱码等问题。
38 0
JSON数据解析实战:从嵌套结构到结构化表格
在信息爆炸的时代,从杂乱数据中提取精准知识图谱是数据侦探的挑战。本文以Google Scholar为例,解析嵌套JSON数据,提取文献信息并转换为结构化表格,通过Graphviz制作技术关系图谱,揭示文献间的隐秘联系。代码涵盖代理IP、请求头设置、JSON解析及可视化,提供完整实战案例。
JSON数据解析实战:从嵌套结构到结构化表格
淘宝商品详情API接口概述与JSON数据示例
淘宝商品详情API是淘宝开放平台提供的核心接口之一,为开发者提供了获取商品深度信息的能力。以下是技术细节和示例:
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——定义返回的统一 json 结构
本课主要讲解Spring Boot中的全局异常处理方法。在项目开发中,各层操作难免会遇到各种异常,若逐一处理将导致代码耦合度高、维护困难。因此,需将异常处理从业务逻辑中分离,实现统一管理与友好反馈。本文通过定义一个简化的JsonResult类(含状态码code和消息msg),结合全局异常拦截器,展示如何封装并返回标准化的JSON响应,从而提升代码质量和用户体验。
25 0
讲解SSM的xml文件
本文详细介绍了SSM框架中的xml配置文件,包括springMVC.xml和applicationContext.xml,涉及组件扫描、数据源配置、事务管理、MyBatis集成以及Spring MVC的视图解析器配置。
136 1

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等