SpringBoot 集成SpringBatch 批处理框架

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 批处理流程图:

SpringBoot 集成SpringBatch 批处理框架_第1张图片

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 {
	}

}

项目整体结构截图:

SpringBoot 集成SpringBatch 批处理框架_第2张图片

补全日志配置文件、数据库脚本和测试数据:

 
  
  
  
  
  
  
  
  
      
      
      
      
  
  
      
      
          
          
            %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  
          
      
    
        
        
        
        
        
        
        
    
    
		
      
      
      
          
          
          
          
          
          
          
      

SpringBoot 集成SpringBatch 批处理框架_第3张图片

SpringBoot 集成SpringBatch 批处理框架_第4张图片

你可能感兴趣的:(微服务springboot,分布式服务架构)