使用Springboot + mybatis框架
4.1.1 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mlsama</groupId>
<artifactId>batchPay</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>batchPay</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mybatis.version>1.3.2</mybatis.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<!--Spring batch与Quartz的整合包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!--Quartz-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--使用MySQL作为数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--lombok约束-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--日记-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<!--c3p0连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
</project>
4.1.2 application.properties
server.port=8888
#关闭项目启动job自动执行
spring.batch.job.enabled = false
#整合c3p0,要自定义配置类,如:DataSourceConfiguration
spring.datasource.c3p0.driverClass=com.mysql.jdbc.Driver
spring.datasource.c3p0.jdbcUrl=jdbc:mysql://localhost:3306/springbatch
spring.datasource.c3p0.user=root
spring.datasource.c3p0.password=mlsama
spring.datasource.c3p0.maxPoolSize=30
spring.datasource.c3p0.minPoolSize=10
spring.datasource.c3p0.initialPoolSize=10
#mybatis配置
#别名包扫描
mybatis.typeAliasesPackage=com.mlsama.hellospringbatch.pojo
#引入*Mapper.xml文件
mybatis.mapperLocations=classpath:mappers/**/*Mapper.xml
# 引入mybatis主配置文件
mybatis.configLocation=classpath:mybatis-config.xml
4.1.3 整合c3p0,自定义数据源
@Configuration //声明为配置类
public class DataSourceConfiguration {
@Bean(name = "dataSource") //对象及名称
@Primary //主要的候选者
//配置属性,prefix : 前缀 spring.datasource固定
@ConfigurationProperties(prefix = "spring.datasource.c3p0")
public DataSource createDataSource(){
return DataSourceBuilder.create() // 创建数据源构建对象
.type(ComboPooledDataSource.class) // 设置数据源类型
.build(); // 构建数据源对象
}
}
4.1.4 mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 全局的设置-->
<settings>
<!-- 开启缓存 -->
<setting name="cacheEnabled" value="true"/>
<!-- 启用延迟加载功能 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 按需要延迟加载-->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 开启驼峰映射 (方便自动映射) -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
4.1.5 job的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springbatch"></property>
<property name="user" value="root"></property>
<property name="password" value="mlsama"></property>
</bean>-->
<!--DataSource在DataSourceConfiguration中定义-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置spring batch的jobRepository,负责与数据库打交道 -->
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<!-- 配置spring batch的 jobLauncher,用来启动Job-->
<bean id="batchJobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"></property>
</bean>
<!-- 注册job,把job注入到容器中,在jobLauncher启动job时才能从容器中获取要启动的Job -->
<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry"/>
<bean class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry"/>
</bean>
<!--“任务浏览器(JObExplorer)”是“任务存储器(JobRepository)”的只读版本,
像后者一样,它可以通过工厂bean简单的配置生成-->
<bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--读取数据-->
<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="classpath:/batchFiles/86000041-20181008.csv"></property>
<property name="lineMapper" ref="lineMapper"></property>
<property name="linesToSkip" value="1"></property>
</bean>
<bean id="lineMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer" ref="lineTokenizer"></property>
<property name="fieldSetMapper" ref="fieldSetMapper"></property>
</bean>
<bean id="lineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="procCode,account,accountName,amount,payType,reserve"></property>
</bean>
<bean id="fieldSetMapper" class="com.mlsama.hellospringbatch.reader.BatchPayReader"></bean>
<!--核心业务处理-->
<bean id="process" class="com.mlsama.hellospringbatch.processor.BatchPayItemProcessor"></bean>
<!--持久化处理-->
<bean id="write" class="com.mlsama.hellospringbatch.writer.BatchPayWriter"></bean>
<!-- 配置job工作 -->
<batch:job id="batchPayJob" restartable="true">
<batch:step id="batchPayJobStep">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="reader"
processor="process"
writer="write"
commit-interval="10">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
</beans>
4.1.6 数据源(.csv文件)
86000041-20181008.csv
procCode,account,accountName,amount,payType,reserve
86000041,612565688853252536,df,203000,DS,转账
86000041,813565678853252533,ds,240000,DS,转账
86000041,615465688853252531,ed,203000,DS,转账
86000041,614565688853252532,de,200600,DS,转账
86000041,687565688853252534,er,200050,DS,转账
4.1.7 实体类
@Data
public class BatchPay {
/**
* 流水号
*/
private String logSeq;
/**
* 支付机构编码
*/
private String procCode;
/**
* 账号
*/
private String account;
/**
* 户名
*/
private String accountName;
/**
* 金额
*/
private BigDecimal amount;
/**
* 支付类型
*/
private String paySeq;
/**
* 支付类型
*/
private String payType;
/**
* 交易日期
*/
private String tradeDate;
/**
* 交易时间
*/
private String tradeTime;
/**
* 交易结果
*/
private String resultCode;
/**
* 交易返回码
*/
private String respCode;
/**
* 交易返回码描述
*/
private String respMsg;
/**
* 自定义域1
*/
private String reserve;
public BatchPay(String procCode, String account, String accountName, BigDecimal amount, String payType, String reserve) {
this.procCode = procCode;
this.account = account;
this.accountName = accountName;
this.amount = amount;
this.payType = payType;
this.reserve = reserve;
}
@Override
public String toString() {
return "BatchPay{" +
"logSeq='" + logSeq + '\'' +
", procCode='" + procCode + '\'' +
", account='" + account + '\'' +
", accountName='" + accountName + '\'' +
", amount=" + amount +
", payType='" + payType + '\'' +
", paySeq='" + paySeq + '\'' +
", tradeDate='" + tradeDate + '\'' +
", tradeTime='" + tradeTime + '\'' +
", resultCode='" + resultCode + '\'' +
", respCode='" + respCode + '\'' +
", respMsg='" + respMsg + '\'' +
", reserve1='" + reserve + '\'' +
'}';
}
}
4.1.8 读取数据源
使用FlatFileItemReader类,其实已经在job的配置文件中有了配置:
<!--读取数据-->
<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
<!--数据源文件-->
<property name="resource" value="classpath:/batchFiles/86000041-20181008.csv"></property>
<!--将一行映射成一个对象-->
<property name="lineMapper" ref="lineMapper"></property>
<!--跳过第一行-->
<property name="linesToSkip" value="1"></property>
</bean>
<!--行映射器-->
<bean id="lineMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<!--设置行字段-->
<property name="lineTokenizer" ref="lineTokenizer"></property>
<!--进行行对象映射-->
<property name="fieldSetMapper" ref="fieldSetMapper"></property>
</bean>
<bean id="lineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="procCode,account,accountName,amount,payType,reserve"></property>
</bean>
<bean id="fieldSetMapper" class="com.mlsama.hellospringbatch.reader.BatchPayReader"></bean>
将行映射为对象的类需要自定义:
BatchPayReader.java
public class BatchPayReader implements FieldSetMapper<BatchPay>{
@Override
public BatchPay mapFieldSet(FieldSet fieldSet) throws BindException {
return new BatchPay(
//fieldSet里有每一行的数据,从0开始
fieldSet.readString(0),
fieldSet.readString(1),
fieldSet.readString(2),
new BigDecimal(fieldSet.readString(3)),
fieldSet.readString(4),
fieldSet.readString(5)
);
}
}
4.1.9 业务处理
在配置文件中也有了定义
<!--核心业务处理-->
<bean id="process" class="com.mlsama.hellospringbatch.processor.BatchPayItemProcessor"></bean>
BatchPayItemProcessor.Java如下:
@Slf4j
public class BatchPayItemProcessor implements ItemProcessor<BatchPay,BatchPay>{
@Override
public BatchPay process(BatchPay batchPay) throws Exception {
String logSeq = CommonUtil.getLogSeq();
batchPay.setLogSeq(logSeq);
batchPay.setPaySeq(logSeq);
batchPay.setTradeDate(new SimpleDateFormat(CommonConstants.DATA_FORMAT).format(new Date()));
batchPay.setTradeTime(new SimpleDateFormat(CommonConstants.Time_FORMAT).format(new Date()));
batchPay.setResultCode(CommonConstants.RESULT_CODE_0050);
return batchPay;
}
}
4.1.10 持久化
在配置文件中的配置如下:
<!--持久化处理-->
<bean id="write" class="com.mlsama.hellospringbatch.writer.BatchPayWriter"></bean>
BatchPayWriter.Java如下:
@Slf4j
public class BatchPayWriter implements ItemWriter<BatchPay> {
@Autowired
private BatchPayManager batchPayManager;
@Override
public void write(List<? extends BatchPay> list) throws Exception {
log.info("开始持久化数据.list={}",list);
try {
batchPayManager.batchPayInsert(list);
}catch (Exception e){
log.error("持久化数据异常{}.",e);
}
}
}
4.1.11 统一管理层
@Service
public class BatchPayManager {
@Autowired
private BatchPayMapper batchPayMapper;
@Transactional(rollbackFor = Exception.class)
public void batchPayInsert(List<? extends BatchPay> list){
batchPayMapper.batchInsert(list);
}
}
4.1.12 mybatis的mapper层
@Mapper
public interface BatchPayMapper {
void batchInsert(List<? extends BatchPay> list);
}
4.1.13 mybatis的mapper配置
在resource下创建文件夹mappers,创建配置文件BatchPayMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mlsama.hellospringbatch.mapper.BatchPayMapper">
<insert id="batchInsert" parameterType="list">
INSERT INTO t_batch_pay
(
log_seq,
proc_code,
account,
account_name,
amount,
pay_seq,
pay_type,
trade_date,
trade_time,
result_code,
resp_code,
resp_msg,
reserver
)VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.logSeq, jdbcType=VARCHAR},
#{item.procCode, jdbcType=VARCHAR},
#{item.account, jdbcType=VARCHAR},
#{item.accountName, jdbcType=VARCHAR},
#{item.amount, jdbcType=DECIMAL},
#{item.paySeq, jdbcType=VARCHAR},
#{item.payType, jdbcType=VARCHAR},
#{item.tradeDate, jdbcType=VARCHAR},
#{item.tradeTime, jdbcType=VARCHAR},
#{item.resultCode, jdbcType=VARCHAR},
#{item.respCode, jdbcType=VARCHAR},
#{item.respMsg, jdbcType=VARCHAR},
#{item.reserve, jdbcType=VARCHAR}
)
</foreach>
</insert>
</mapper>
4.1.14 job调度层
用于启动job,通过配置在job配置文件中的SimpleJobLauncher启动job.
@Service
@Slf4j
public class BatchPayJobLauncher {
@Resource(name = "batchJobLauncher")
private SimpleJobLauncher batchJobLauncher;
@Resource(name = "batchPayJob")
private Job batchPayJob;
public String doBatchPayJob(){
try {
JobExecution jobExecution = batchJobLauncher.run(batchPayJob, new RunIdIncrementer().getNext(null));
return jobExecution.getStatus().name();
}catch (Exception e){
log.error("执行job:batchPayJob发生异常{}",e);
}
return null;
}
}
4.1.15 控制层
接受页面请求,调用job调度层方法,启动job
@Controller
@RequestMapping("/batchPay")
public class BatchPayController {
@Autowired
private BatchPayJobLauncher batchPayJobLauncher;
@ResponseBody
@GetMapping("/doBatchPayJob")
public String doBatchPayJob(){
String result = batchPayJobLauncher.doBatchPayJob();
if (StringUtils.isBlank(result)){
result = "调用失败.发生异常";
}
return result;
}
}
4.1.16 项目启动类
@SpringBootApplication //springboot启动
//@EnableBatchProcessing //加载所有的job,这里不能有这个,否则不能调度
@ImportResource(locations = "classpath:*-config.xml")
public class Application {
public static void main(String[] args) {
/** 创建SpringApplication对象 */
SpringApplication springApplication =
new SpringApplication(Application.class);
/** 设置横幅关闭 */
springApplication.setBannerMode(Banner.Mode.OFF);
/** 运行 */
springApplication.run(args);
}
}
4.1.17 项目结构
运行项目启动类,访问: http://localhost:8888/batchPay/doBatchPayJob