SpringBatch 核心组件简介:
1)JobRepository:用来注册Job容器,设置数据库相关属性。
2)JobLauncher:用来启动Job的接口
3)Job:我们要实际执行的任务,包含一个或多个
4)Step:即步骤,包括:ItemReader->ItemProcessor->ItemWriter
5)ItemReader:用来读取数据,做实体类与数据字段之间的映射。比如读取csv文件中的人员数据,之后对应实体AuthUser的字段做mapper
6)ItemProcessor:用来处理数据的接口,同时可以做数据校验(设置校验器,使用JSR-303(hibernate-validator)注解)
7)ItemWriter:用来输出数据的接口,设置数据库源。编写预处理SQL插入语句
使用说明:在自定义的SpringBatch配置对象中一一实列化七大组件,并且在程序入口开启@EnableBatchProcessing
package com.zzg.batch;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement
@MapperScan("com.zzg.batch.mapper")
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
System.out.println("============= SpringBoot gcxt-system-provider Service Start Success =============");
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
// 注意这里要指向原先用main方法执行的Application启动类
return builder.sources(Application.class);
}
}
SpringBatch 批处理流程图:
SpringBatch 实践
第一步:依赖核心jar文件:
4.0.0
com.zzg
jreport
0.0.1-SNAPSHOT
pom
org.springframework.boot
spring-boot-starter-parent
2.1.1.RELEASE
UTF-8
UTF-8
1.8
1.3.2
8.0.11
1.1.9
2.6
1.10
3.8.1
3.6
2.6
3.2.1
1.3.1
1.2.48
6.10.0
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.projectlombok
lombok
${lombok.version}
provided
org.mybatis.spring.boot
mybatis-spring-boot-starter
${mybatis-spring-boot-starter.version}
mysql
mysql-connector-java
${mysql-connector-java.version}
runtime
com.alibaba
druid-spring-boot-starter
${com.alibaba.druid.version}
com.github.pagehelper
pagehelper
4.1.6
commons-lang
commons-lang
${commons-lang.version}
org.apache.commons
commons-lang3
${commons-lang3.version}
commons-codec
commons-codec
${commons-codec.version}
commons-net
commons-net
${commons-net.version}
commons-io
commons-io
${commons-io.version}
commons-collections
commons-collections
${commons-collections.version}
commons-fileupload
commons-fileupload
${common-fileupload.version}
io.springfox
springfox-swagger2
2.7.0
io.springfox
springfox-swagger-ui
2.7.0
com.alibaba
fastjson
${fastjson.version}
org.springframework.boot
spring-boot-starter-batch
第二步:application.properties 配置文件
# 指定服务端口
server.port=7090
# 指定服务 名称
# server.context-path=/jreport
#mybatis xml 文件配置
mybatis.mapper-locations=classpath*:mapper/batch/*Mapper.xml
mybatis.type-aliases-package=com.zzg.batch.domain
# MyBatis mysql8 配置
spring.datasource.url=jdbc:mysql://192.168.1.**:3306/boot-security?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true
spring.datasource.username=**
spring.datasource.password=**
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Druid 配置
# 初始化时建立物理连接的个数
spring.datasource.druid.initial-size=5
# 最大连接池数量
spring.datasource.druid.max-active=30
# 最小连接池数量
spring.datasource.druid.min-idle=5
# 获取连接时最大等待时间,单位毫秒
spring.datasource.druid.max-wait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=60000
# 连接保持空闲而不被驱逐的最小时间
spring.datasource.druid.min-evictable-idle-time-millis=300000
# 用来检测连接是否有效的sql,要求是一个查询语句
spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
# 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
spring.datasource.druid.test-while-idle=true
# 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
spring.datasource.druid.test-on-borrow=false
# 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
spring.datasource.druid.test-on-return=false
# 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
spring.datasource.druid.pool-prepared-statements=true
# 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=50
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计
#spring.datasource.druid.filters=stat,wall
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
# 合并多个DruidDataSource的监控数据
spring.datasource.druid.use-global-data-source-stat=true
# 配置sql 注入方式
spring.datasource.druid.filters=stat
# 日志文件配置
logging.config=classpath:logback.xml
# springboot 批处理配置
spring.batch.job.enabled=false
spring.batch.initialize-schema=always
第三步:配置类
package com.zzg.batch.config;
import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.PlatformTransactionManager;
import com.zzg.batch.domain.AuthUser;
import com.zzg.batch.processor.CVSItemProcessor;
import com.zzg.batch.processor.listener.CSVJobListener;
import com.zzg.batch.processor.validator.BeanValidator;
/**
* springboot batch 配置类
* @author zzg
*
*/
@Configuration
@EnableBatchProcessing // 开启批处理的支持
public class BatchConfig {
@Autowired
private DataSource dataSource;
@Autowired
private PlatformTransactionManager transactionManager;
/**
* ItemReader定义:读取文件数据+entirty映射
* @return
*/
@Bean
public ItemReader reader(){
// 使用FlatFileItemReader去读cvs文件,一行即一条数据
FlatFileItemReader reader = new FlatFileItemReader<>();
// 设置文件处在路径
reader.setResource(new ClassPathResource("user.csv"));
// entity与csv数据做映射
reader.setLineMapper(new DefaultLineMapper() {
{
setLineTokenizer(new DelimitedLineTokenizer() {
{
setNames(new String[]{"id", "password"});
}
});
setFieldSetMapper(new BeanWrapperFieldSetMapper() {
{
setTargetType(AuthUser.class);
}
});
}
});
return reader;
}
/**
* 注册ItemProcessor: 处理数据
* @return
*/
@Bean
public ItemProcessor processor(){
CVSItemProcessor cvsItemProcessor = new CVSItemProcessor();
cvsItemProcessor.setValidator(new BeanValidator());
return cvsItemProcessor;
}
/**
* ItemWriter定义:指定datasource,设置批量插入sql语句,写入数据库
* @param dataSource
* @return
*/
@Bean
public ItemWriter writer(){
// 使用jdbcBcatchItemWrite写数据到数据库中
JdbcBatchItemWriter writer = new JdbcBatchItemWriter<>();
// 设置有参数的sql语句
writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider());
String sql = "insert into auth_user (id, password)" + " values(:id, :password)";
writer.setSql(sql);
writer.setDataSource(dataSource);
return writer;
}
/**
* JobRepository定义:设置数据库,注册Job容器
* @param dataSource
* @param transactionManager
* @return
* @throws Exception
*/
@Bean
public JobRepository cvsJobRepository() throws Exception{
JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
jobRepositoryFactoryBean.setDatabaseType("mysql");
jobRepositoryFactoryBean.setTransactionManager(transactionManager);
jobRepositoryFactoryBean.setDataSource(dataSource);
return jobRepositoryFactoryBean.getObject();
}
/**
* jobLauncher定义:
* @param dataSource
* @param transactionManager
* @return
* @throws Exception
*/
@Bean
public SimpleJobLauncher csvJobLauncher() throws Exception{
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
// 设置jobRepository
jobLauncher.setJobRepository(cvsJobRepository());
return jobLauncher;
}
/**
* 定义job
* @param jobs
* @param step
* @return
*/
@Bean
public Job importJob(JobBuilderFactory jobs, Step step){
return jobs.get("importCsvJob")
.incrementer(new RunIdIncrementer())
.flow(step)
.end()
.listener(csvJobListener())
.build();
}
/**
* 注册job监听器
* @return
*/
@Bean
public CSVJobListener csvJobListener(){
return new CSVJobListener();
}
/**
* step定义:步骤包括ItemReader->ItemProcessor->ItemWriter 即读取数据->处理校验数据->写入数据
* @param stepBuilderFactory
* @param reader
* @param writer
* @param processor
* @return
*/
@Bean
public Step step(StepBuilderFactory stepBuilderFactory, ItemReader reader,
ItemWriter writer, ItemProcessor processor){
return stepBuilderFactory
.get("step")
.chunk(65000) // Chunk的机制(即每次读取一条数据,再处理一条数据,累积到一定数量后再一次性交给writer进行写入操作)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
}
package com.zzg.batch.config;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
/**
* druid 监控配置
* @author zzg
*
*/
@Configuration
public class DruidConfig {
@Bean
public ServletRegistrationBean druidServletRegistrationBean() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
servletRegistrationBean.setServlet(new StatViewServlet());
servletRegistrationBean.addUrlMappings("/druid/*");
servletRegistrationBean.addInitParameter("allow", "");
servletRegistrationBean.addInitParameter("deny", "");
servletRegistrationBean.addInitParameter("loginUsername", "admin");
servletRegistrationBean.addInitParameter("loginPassword", "admin");
return servletRegistrationBean;
}
/**
* 注册DruidFilter拦截
*
* @return
*/
@Bean
public FilterRegistrationBean duridFilterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
Map initParams = new HashMap();
//设置忽略请求
initParams.put("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
filterRegistrationBean.setInitParameters(initParams);
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
}
package com.zzg.batch.config;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.github.pagehelper.PageHelper;
/**
* mybatis 配置对象
* @author zzg
*
*/
@Configuration
public class MyBatisConfig {
/**
* 分页对象实列化
* @return
*/
@Bean
public PageHelper pageHelper() {
PageHelper pageHelper = new PageHelper();
Properties p = new Properties();
p.setProperty("offsetAsPageNum", "true");
p.setProperty("rowBoundsWithCount", "true");
p.setProperty("reasonable", "true");
p.setProperty("dialect", "mysql");
pageHelper.setProperties(p);
return pageHelper;
}
}
package com.zzg.batch.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.swagger.annotations.ApiOperation;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket buildDocket() {
ParameterBuilder tokenPar = new ParameterBuilder();
List pars = new ArrayList();
tokenPar.name("X-CSRF-TOKEN").description("令牌").modelRef(new ModelRef("string")).parameterType("header")
.required(false).build();
pars.add(tokenPar.build());
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)).paths(PathSelectors.any())
.build().globalOperationParameters(pars).apiInfo(buildApiInf());
}
private ApiInfo buildApiInf() {
return new ApiInfoBuilder().title("****").termsOfServiceUrl("http://www.baidu.cn/")
.description("API接口")
.contact(new Contact("baidu", "http://www.baidu.cn/", "[email protected]"))
.version("2.0").build();
}
}
业务逻辑层代码:model、service、mapper层的相关代码:
package com.zzg.batch.domain;
import java.util.Date;
public class AuthUser {
private Integer id;
private String password;
private Date lastLogin;
private String isSuperuser;
private String username;
private String firstName;
private String lastName;
private String email;
private String isStaff;
private String isActive;
private Date dateJoined;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password == null ? null : password.trim();
}
public Date getLastLogin() {
return lastLogin;
}
public void setLastLogin(Date lastLogin) {
this.lastLogin = lastLogin;
}
public String getIsSuperuser() {
return isSuperuser;
}
public void setIsSuperuser(String isSuperuser) {
this.isSuperuser = isSuperuser;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username == null ? null : username.trim();
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName == null ? null : firstName.trim();
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName == null ? null : lastName.trim();
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email == null ? null : email.trim();
}
public String getIsStaff() {
return isStaff;
}
public void setIsStaff(String isStaff) {
this.isStaff = isStaff;
}
public String getIsActive() {
return isActive;
}
public void setIsActive(String isActive) {
this.isActive = isActive;
}
public Date getDateJoined() {
return dateJoined;
}
public void setDateJoined(Date dateJoined) {
this.dateJoined = dateJoined;
}
}
package com.zzg.batch.mapper;
import java.util.List;
import java.util.Map;
import com.zzg.batch.domain.AuthUser;
public interface AuthUserMapper {
int deleteByPrimaryKey(Integer id);
int insert(AuthUser record);
int insertSelective(AuthUser record);
AuthUser selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(AuthUser record);
int updateByPrimaryKey(AuthUser record);
// 方法梳理
List selectAll(Map paramter);
}
package com.zzg.batch.service;
import java.util.List;
import java.util.Map;
import com.zzg.batch.domain.AuthUser;
import com.zzg.jreport.common.BaseService;
import com.zzg.jreport.common.page.PageData;
import com.zzg.jreport.common.page.PageParam;
public interface AuthUserService extends BaseService {
// 方法梳理
List selectAll(Map paramter);
PageData selectAllPage(Map parame, PageParam rb);
// 事务测试
void transaction();
}
package com.zzg.batch.service.impl;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zzg.batch.domain.AuthUser;
import com.zzg.batch.mapper.AuthUserMapper;
import com.zzg.batch.service.AuthUserService;
import com.zzg.jreport.common.convert.SimpleTypeConverterUtil;
import com.zzg.jreport.common.page.PageData;
import com.zzg.jreport.common.page.PageParam;
@Service
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
public class AuthUserServiceImpl implements AuthUserService {
@Autowired
private AuthUserMapper mapper;
@Override
public Long insert(AuthUser entity) {
// TODO Auto-generated method stub
Integer num = mapper.insertSelective(entity);
return Long.valueOf(num);
}
@Override
public void updateByPrimaryKeySelective(AuthUser entity) {
// TODO Auto-generated method stub
mapper.updateByPrimaryKeySelective(entity);
}
@Override
public AuthUser selectByPrimaryKey(String sid) {
// TODO Auto-generated method stub
return mapper.selectByPrimaryKey(SimpleTypeConverterUtil.convertIfNecessary(sid, int.class));
}
@Override
public void deleteByPrimaryKey(String sid) {
// TODO Auto-generated method stub
mapper.deleteByPrimaryKey(SimpleTypeConverterUtil.convertIfNecessary(sid, int.class));
}
@Override
public List selectAll(Map paramter) {
// TODO Auto-generated method stub
return mapper.selectAll(paramter);
}
@Override
public PageData selectAllPage(Map parame, PageParam rb) {
// TODO Auto-generated method stub
PageData pageData = new PageData();
PageHelper.startPage(rb.getPageNo(), rb.getLimit());
List rs = mapper.selectAll(parame);
PageInfo pageInfo = new PageInfo(rs);
pageData.setData(pageInfo.getList());
pageData.setPageNum(pageInfo.getPageNum());
pageData.setPageSize(pageInfo.getPageSize());
pageData.setTotalCount(pageInfo.getTotal());
return pageData;
}
@Override
public void transaction() {
// TODO Auto-generated method stub
AuthUser admin = new AuthUser();
admin.setId(1);
admin.setUsername("admin");
mapper.updateByPrimaryKeySelective(admin);
int a = 1 / 0;
AuthUser superMan = new AuthUser();
superMan.setId(2);
superMan.setUsername("superMan");
mapper.updateByPrimaryKeySelective(superMan);
}
}
package com.zzg.batch.controller;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONObject;
import com.zzg.batch.domain.AuthUser;
import com.zzg.batch.service.AuthUserService;
import com.zzg.jreport.common.controller.AbstractController;
import com.zzg.jreport.common.page.PageData;
import com.zzg.jreport.common.page.PageParam;
import com.zzg.jreport.response.JreportResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@Controller
@RequestMapping("/api/auth/user")
@Api(value = "用户Controlle", tags = "用户操作服务")
public class AuthUserController extends AbstractController {
@Autowired
private AuthUserService service;
@ApiOperation(httpMethod = "POST", value = "用户对象保存")
@RequestMapping(value = "/insert", method = { RequestMethod.POST }, produces = "application/json;charset=UTF-8")
@ResponseBody
public JreportResponse insert(
@RequestBody @ApiParam(name = "用户对象", value = "json格式对象", required = true) AuthUser entity) {
Long engSid = service.insert(entity);
return JreportResponse.ok(engSid);
}
@ApiOperation(httpMethod = "POST", value = "用户对象更新")
@RequestMapping(value = "/update", method = { RequestMethod.POST }, produces = "application/json;charset=UTF-8")
@ResponseBody
public JreportResponse update(
@RequestBody @ApiParam(name = "用户对象", value = "json格式对象", required = true) AuthUser entity) {
service.updateByPrimaryKeySelective(entity);
return JreportResponse.ok();
}
@RequestMapping(value="/find", method={RequestMethod.POST}, produces = "application/json;charset=UTF-8")
@ResponseBody
@ApiOperation(httpMethod = "POST", value = "用户查询")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "主键", required = false, dataType = "Integer", paramType = "query"),
@ApiImplicitParam(name = "username", value = "用户名称", required = false, dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "email", value = "用户邮箱", required = false, dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "isStaff", value = "是否在职:1 在职、2:离职", required = false, dataType = "Integer", paramType = "query"),
@ApiImplicitParam(name = "isActive", value = "激活状态:1 已激活、2:未激活", required = false, dataType = "Integer", paramType = "query")
})
public JreportResponse find(@RequestBody @ApiParam(name = "用户对象", value = "json格式对象", required = true) JSONObject entity) {
Map param = JSONObject.toJavaObject(entity, Map.class);
List list = service.selectAll(param);
return JreportResponse.ok(list);
}
@RequestMapping(value="/findByPage", method={RequestMethod.POST}, produces = "application/json;charset=UTF-8")
@ResponseBody
@ApiOperation(httpMethod = "POST", value = "用户分页查询")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "主键", required = false, dataType = "Integer", paramType = "query"),
@ApiImplicitParam(name = "username", value = "用户名称", required = false, dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "email", value = "用户邮箱", required = false, dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "isStaff", value = "是否在职:1 在职、2:离职", required = false, dataType = "Integer", paramType = "query"),
@ApiImplicitParam(name = "isActive", value = "激活状态:1 已激活、2:未激活", required = false, dataType = "Integer", paramType = "query")
})
public JreportResponse findByPage(@RequestBody @ApiParam(name = "用户对象", value = "json格式对象", required = true) JSONObject entity) {
Map param = JSONObject.toJavaObject(entity, Map.class);
PageParam rb = super.initPageBounds(param);
PageData pageList = service.selectAllPage(param, rb);
return JreportResponse.ok(pageList);
}
}
package com.zzg.batch.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.zzg.batch.processor.listener.CSVJobListener;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@Controller
@RequestMapping("/api/batch")
@Api(value = "批处理Controlle", tags = "批处理操作服务")
public class BatchController {
// 日志服务处理
private Logger logger = LoggerFactory.getLogger(BatchController.class);
@Autowired
private SimpleJobLauncher launcher;
@Autowired
private Job job;
@ApiOperation(httpMethod = "POST", value = "用户对象保存")
@RequestMapping(value = "/init", method = { RequestMethod.POST }, produces = "application/json;charset=UTF-8")
@ResponseBody
public void insert() {
// 后置参数:使用JobParameters中绑定参数
try{
JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
.toJobParameters();
launcher.run(job, jobParameters);
} catch(Exception e){
e.printStackTrace();
logger.error(e.getMessage());
}
}
}
package com.zzg.batch.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.zzg.batch.service.AuthUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@Controller
@RequestMapping("/api/trans")
@Api(value = "事务处理Controlle", tags = "事务处理操作服务")
public class TransactionController {
@Autowired
private AuthUserService service;
@ApiOperation(httpMethod = "POST", value = "事务功能测试")
@RequestMapping(value = "/init", method = { RequestMethod.POST }, produces = "application/json;charset=UTF-8")
@ResponseBody
public void init() {
service.transaction();
}
}
id, password, last_login, is_superuser, username,
first_name, last_name,
email, is_staff,
is_active, date_joined
and id = #{id}
and username = #{username}
and email = #{email}
and is_staff = #{isStaff}
and is_active = #{isActive}
delete from
auth_user
where id = #{id,jdbcType=INTEGER}
insert into auth_user (id,
password, last_login,
is_superuser, username, first_name,
last_name,
email, is_staff,
is_active, date_joined)
values (#{id,jdbcType=INTEGER},
#{password,jdbcType=VARCHAR},
#{lastLogin,jdbcType=TIMESTAMP},
#{isSuperuser,jdbcType=VARCHAR}, #{username,jdbcType=VARCHAR},
#{firstName,jdbcType=VARCHAR},
#{lastName,jdbcType=VARCHAR},
#{email,jdbcType=VARCHAR},
#{isStaff,jdbcType=VARCHAR},
#{isActive,jdbcType=VARCHAR}, #{dateJoined,jdbcType=TIMESTAMP})
insert into auth_user
id,
password,
last_login,
is_superuser,
username,
first_name,
last_name,
email,
is_staff,
is_active,
date_joined,
#{id,jdbcType=INTEGER},
#{password,jdbcType=VARCHAR},
#{lastLogin,jdbcType=TIMESTAMP},
#{isSuperuser,jdbcType=VARCHAR},
#{username,jdbcType=VARCHAR},
#{firstName,jdbcType=VARCHAR},
#{lastName,jdbcType=VARCHAR},
#{email,jdbcType=VARCHAR},
#{isStaff,jdbcType=VARCHAR},
#{isActive,jdbcType=VARCHAR},
#{dateJoined,jdbcType=TIMESTAMP},
update auth_user
password = #{password,jdbcType=VARCHAR},
last_login = #{lastLogin,jdbcType=TIMESTAMP},
is_superuser = #{isSuperuser,jdbcType=VARCHAR},
username = #{username,jdbcType=VARCHAR},
first_name = #{firstName,jdbcType=VARCHAR},
last_name = #{lastName,jdbcType=VARCHAR},
email = #{email,jdbcType=VARCHAR},
is_staff = #{isStaff,jdbcType=VARCHAR},
is_active = #{isActive,jdbcType=VARCHAR},
date_joined = #{dateJoined,jdbcType=TIMESTAMP},
where id = #{id,jdbcType=INTEGER}
update auth_user
set password = #{password,jdbcType=VARCHAR},
last_login =
#{lastLogin,jdbcType=TIMESTAMP},
is_superuser =
#{isSuperuser,jdbcType=VARCHAR},
username = #{username,jdbcType=VARCHAR},
first_name = #{firstName,jdbcType=VARCHAR},
last_name =
#{lastName,jdbcType=VARCHAR},
email = #{email,jdbcType=VARCHAR},
is_staff = #{isStaff,jdbcType=VARCHAR},
is_active =
#{isActive,jdbcType=VARCHAR},
date_joined =
#{dateJoined,jdbcType=TIMESTAMP}
where id = #{id,jdbcType=INTEGER}
SpringBatch批处理涉及:批处理类、批处理监听器、批处理校验器
package com.zzg.batch.processor;
import org.springframework.batch.item.validator.ValidatingItemProcessor;
import org.springframework.batch.item.validator.ValidationException;
import com.zzg.batch.domain.AuthUser;
public class CVSItemProcessor extends ValidatingItemProcessor {
// 局部常量
// public static final String YES = "1";
// public static final String NO = "2";
@Override
public AuthUser process(AuthUser item) throws ValidationException {
// TODO Auto-generated method stub
super.process(item);
// if("是".equalsIgnoreCase(item.getIsSuperuser())){
// item.setIsSuperuser(YES);
// } else {
// item.setIsSuperuser(NO);
// }
//
// if("是".equalsIgnoreCase(item.getIsActive())){
// item.setIsActive(YES);
// } else {
// item.setIsActive(NO);
// }
//
// if("是".equalsIgnoreCase(item.getIsStaff())){
// item.setIsStaff(YES);
// } else {
// item.setIsStaff(NO);
// }
return item;
}
}
package com.zzg.batch.processor.listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
public class CSVJobListener implements JobExecutionListener {
private Logger logger = LoggerFactory.getLogger(CSVJobListener.class);
private long startTime;
private long endTime;
@Override
public void afterJob(JobExecution arg0) {
// TODO Auto-generated method stub
endTime = System.currentTimeMillis();
logger.info("job process end...");
logger.info("spend time: " + (endTime - startTime) + "ms");
}
@Override
public void beforeJob(JobExecution arg0) {
// TODO Auto-generated method stub
startTime = System.currentTimeMillis();
logger.info("job process start...");
}
}
package com.zzg.batch.processor.validator;
import org.springframework.batch.item.validator.ValidationException;
import org.springframework.batch.item.validator.Validator;
import org.springframework.beans.factory.InitializingBean;
public class BeanValidator implements Validator, InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
}
@Override
public void validate(T value) throws ValidationException {
}
}
项目整体结构截图:
补全日志配置文件、数据库脚本和测试数据:
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n
ERROR
ACCEPT
DENY
${log_dir}/%d{yyyy-MM-dd}/neo4j-error-log.log
${maxHistory}
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
WARN
ACCEPT
DENY
${log_dir}/%d{yyyy-MM-dd}/neo4j-warn-log.log
${maxHistory}
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
INFO
ACCEPT
DENY
${log_dir}/%d{yyyy-MM-dd}/neo4j-info-log.log
${maxHistory}
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
DEBUG
ACCEPT
DENY
${log_dir}/%d{yyyy-MM-dd}/neo4j-debug-log.log
${maxHistory}
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n