SpringBoot(五):Spring Boot企业级开发

1.安全控制Spring Security

1.1 了解Spring Security

1.1.1 什么是Spring Security

Spring Security是专门针对基于Spring的项目的安全框架。

主要有两个概念:认证和授权。认证即确认用户可以访问当前系统,授权即确认用户在当前系统下所拥有的功能权限

1.1.2 Spring Security的配置

开启Spring Security过滤器的支持,只需要extends AbstractSecurityWebApplicationInitializer开启过滤器的支持

配置:在配置类上注解@EnableWebSecurity,并让这个类继承WebSecurityConfigurerAdapter。通过写configure方法来配置相关的安全配置

1.1.3 用户认证

认证需要我们有一套用户数据的来源,而授权则是对于某个用户有相应的角色权限。通过重写configure方法实现定制。

1.1.3.1 内存中的用户

@Override
	protected void configure(AuthenticationManagerBuilder auth)
			throws Exception {
		auth.inMemoryAuthentication().withUser("xp").password("xp").roles("ROLE_ADMIN")
		.and()
		.withUser("yxx").password("yxx").roles("ROLE_USER");
	}

1.1.3.2 jdbc中的用户

@Autowired
	javax.sql.DataSource dataSource;	
    protected void configure(AuthenticationManagerBuilder auth)
			throws Exception {
		auth.jdbcAuthentication().dataSource(dataSource);
	}

此处的Spring Security是默认的数据库结构的。还可以自动以我们的查询用户和权限的SQL

protected void configure(AuthenticationManagerBuilder auth)
			throws Exception {
		auth.jdbcAuthentication().dataSource(dataSource)
			.usersByUsernameQuery("select username,password from myusers where username = ?")
			.authoritiesByUsernameQuery("select username,role from roles where username = ? ");
		
	}

1.1.3.3 通用的用户

自定义实现UserDetailsService接口

public class CustomUserService implements UserDetailsService {

	@Autowired
	SysUserRepository userRepository;
	
	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		SysUser user =  userRepository.findByUserName(username);
		ArrayList<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
		authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
		return new User(user.getUsername(),user.getPassword(),authorities);
	}

}
@Autowired
	UserDetailsService customUserService(){
		return new CustomUserService();
	}

protected void configure(AuthenticationManagerBuilder auth)
			throws Exception {
		auth.userDetailsService(customUserService());
	}

1.1.3.4 请求授权

Spring Security通过重写实现请求拦截。

protected void configure(HttpSecurity http) throws Exception {}

Spring Security通过以下匹配器来匹配请求路径:

antMatchers:Ant风格的路径匹配

regexMatchers:正则表达式匹配路径

anyRequest:匹配所有请求路径

匹配完路径之后,需要对当前用户的信息进行安全处理,处理方法如下:

access(String):EL表达式为true可以访问

anonymous():匿名可以访问

denyAll():用户不能访问

fullyAuthenticated():用户完全认证可访问(非remember me下自动登录)

hasAnyAuthority(String ...):如果用户有参数,则起着任意权限可以访问

hasAuthority(String):有参数,则可以访问

hasAnyRole(String ...):如果用户有参数,则起着任意角色可以访问

hasRole(String):如果用户有参数,则可以访问

hasIpAddress(String):如果用户来自参数中的IP可以访问

permitAll():所有人可以访问

rememberMe():允许通过remember-me登录的用户访问

authenticated():用户登录后可访问

protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()//开始请求权限配置
			.antMatchers("/admin/**").hasRole("ROLE_ADMIN")///admin/**路径下拥有ROLE_ADMIN角色的用户可以访问
			.antMatchers("/user/**").hasAnyAuthority("ROLE_ADMIN","ROLE_USER")///user/**路径下,拥有ROLE_ADMIN或ROLE_USER都可以访问
			.anyRequest().authenticated();//其余所有请求都需要登录后才能访问
	}

1.1.3.5 定制登录行为

重写configure来定制登录行为

protected void configure(HttpSecurity http) throws Exception {
		http.formLogin()//通过formLogin定制登录操作
			.loginPage("/login")
			.defaultSuccessUrl(".index")
			.failureUrl("/login?error")
			.permitAll()
			.and()
			.rememberMe()//cookie存储用户信息
				.tokenValiditySeconds(1209600)//cookie有效时间
				.key("myKey")//cookie中的私钥
			.and()
			.logout()
				.logoutUrl("/custom-logout")
				.logoutSuccessUrl("/logout-success")
				.permitAll();
	}

1.2 Spring Boot的支持

主要通过SecurityAutoConfiguration和SecurityProperties来完成配置

当我们需要自己拓展时,只需要配置类继承WebSecurityConfigurerAdapter类即可,无需使用@EnableWebSecurity

1.3 实战

用Spring Boot下的Spring Security的配置,完成简单的认证授权的功能。通过Spring Data Jpa获取用户数据,页面模板用Thymeleaf(我的这个例子没有跑通,选择正确的账户也没能进,不知道为什么)

package com.xupeng.xupeng20191202V3.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class SysRole {
	@Id
	@GeneratedValue
	private Long id;
	
	//角色名称
	private String name;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	
}
package com.xupeng.xupeng20191202V3.domain;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javassist.SerialVersionUID;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
//实现了UserDetails后,我们的用户实体即为SpringSecurity所使用的的用户
public class SysUser implements UserDetails {
	
	private static final long SerialVersionUID = 1L;
	
	@Id
	@GeneratedValue
	private Long id;
	
	private String username;
	
	private String password;
	
	//配置用户和角色多对多的关系
	@ManyToMany(cascade={CascadeType.REFRESH},fetch=FetchType.EAGER)
	private List<SysRole> roles;
	

	@Override
	//重写该方法,将用户的角色作为权限
	public Collection<? extends GrantedAuthority> getAuthorities() {
		List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
		List<SysRole> roles = this.getRoles();
		for(SysRole role : roles){
			auths.add(new SimpleGrantedAuthority(role.getName()));
		}
		return auths;
	}

	@Override
	public String getPassword() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getUsername() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isAccountNonExpired() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isAccountNonLocked() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isEnabled() {
		// TODO Auto-generated method stub
		return false;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public List<SysRole> getRoles() {
		return roles;
	}

	public void setRoles(List<SysRole> roles) {
		this.roles = roles;
	}

	public static long getSerialversionuid() {
		return SerialVersionUID;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	

}
package com.xupeng.xupeng20191202V3.domain;

public class Msg {
	private String title;
	private String content;
	private String etraInfo;
	
	public Msg(String title,String content,String etraInfo) {
		super();
		this.title = title;
		this.content = content;
		this.etraInfo = etraInfo;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getEtraInfo() {
		return etraInfo;
	}

	public void setEtraInfo(String etraInfo) {
		this.etraInfo = etraInfo;
	}
	
	
}
package com.xupeng.xupeng20191202V3.dao;

import org.springframework.data.jpa.repository.JpaRepository;

import com.xupeng.xupeng20191202V3.domain.SysUser;

public interface SysUserRepository extends JpaRepository<SysUser, Long> {

	SysUser findByUsername(String username);
}
package com.xupeng.xupeng20191202V3.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.xupeng.xupeng20191202V3.dao.SysUserRepository;
import com.xupeng.xupeng20191202V3.domain.SysUser;

//自定义需实现UserDetailsService接口
public class CustomUserService implements UserDetailsService {

	@Autowired
	SysUserRepository userRepository;
	
	//重写loadUserByUsername方法获得用户
	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		SysUser user = userRepository.findByUsername(username);
		if(user == null){
			throw new UsernameNotFoundException("用户名不存在");
		}
		return user;//当前用户实现了UserDetails接口,可直接返回给Spring Security
	}

}
package com.xupeng.xupeng20191202V3.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@SuppressWarnings("deprecation")
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/login").setViewName("login");
	}
}
package com.xupeng.xupeng20191202V3.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

import com.xupeng.xupeng20191202V3.service.CustomUserService;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Bean
	UserDetailsService customUserService(){
		return new CustomUserService();
	}
	
	@Override
	protected void configure(AuthenticationManagerBuilder auth)
			throws Exception {
		auth.userDetailsService(customUserService());
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.anyRequest().authenticated()
			.and()
			.formLogin()
				.loginPage("/login")
				.failureUrl("/login?error")
				.permitAll()
			.and()
			.logout().permitAll();
			
	}
	
}
package com.xupeng.xupeng20191202V3.web;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.xupeng.xupeng20191202V3.domain.Msg;

@Controller
public class HomeController {

	@RequestMapping("/")
	public String index(Model model){
		Msg msg = new Msg("测试标题", "测试内容", "额外信息,只对管理员显示");
		model.addAttribute("msg",msg);
		return "home";
	}
}
package com.xupeng.xupeng20191202V3;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Xupeng20191202V3Application {

	public static void main(String[] args) {
		SpringApplication.run(Xupeng20191202V3Application.class, args);
	}

}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"><!-- SpringSecurity的标签支持 -->
<head>
<meta charset="UTF-8" />
<title sec:authentication="name"></title><!-- 获取当前用户的用户名 -->
<link th:href="@{bootstrap/css/bootstrap.min.css}" rel="stylesheet"/>
<link th:href="@{bootstrap/css/bootstrap-theme.min.css}" rel="stylesheet"/>
<style type="text/css">
body{
	padding-top: 50px;
}
.starter-template{
	padding:40px 15px;
	text-align: center;
}
</style>
</head>
<body>
	<nav class="navbar navbar-inverse navbar-fixed-top">
		<div class="container">
			<div class="navbar-header">
				<a class="navbar-brand" href="#">Spring Security演示</a>
			</div>
		</div>
		<div id="navbar" class="collapse navbar-collapse">
			<ul class="nav navbar-nav">
				<li><a th:href="@{/}">首页</a></li>
			</ul>
		</div>
	</nav>

	<div class="container">
		<div class="starter-template">
			<h1 th:text="${msg.title}"></h1>
			<p class="bg-primary" th:text="${msg.content}"></p>
			<div sec:authorize="hasRole('ROLE_ADMIN')"><!-- 管理员显示这个 -->
				<p class="bg-info" th:text="${msg.etraInfo}"></p>
			</div>
			<div sec:authorize="hasRole(ROLE_USER)"><!-- 普通用户显示这个 -->
				<p class="bg-info">无更多信息显示</p>
			</div>
			<form th:action="@{/logout}" method="post">
				<input type="submit" class="btn btn-primary" value="注销" /><!-- 注销路径 -->
			</form>
		</div>
	</div>

</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>登录页面</title>
<link th:href="@{bootstrap/css/bootstrap.min.css}" rel="stylesheet" />
<link th:href="@{bootstrap/css/bootstrap-theme.min.css}" rel="stylesheet"/>
<style type="text/css">
body{
	padding-top: 50px;
}
.starter-template{
	padding:40px 15px;
	text-align: center;
}
</style>
</head>
<body>
	<nav class="navbar navbar-inverse navbar-fixed-top">
		<div class="container">
			<div class="navbar-header">
				<a class="navbar-brand" href="#">Spring Security演示</a>
			</div>
		</div>
		<div id="navbar" class="collapse navbar-collapse">
			<ul class="nav navbar-nav">
				<li><a th:href="@{/}">首页</a></li>
			</ul>
		</div>
	</nav>
	<div class="container">
		<div class="starter-template">
			<p th:if="${param.logout}" class="bg-warning">已成功注销</p>
		<p th:if="${param.error}" class="bg-danger">${"param.error"}有错误,请重试</p>
				<h2>使用账号密码登录</h2>
				<form name="form" th:action="@{/login}" method="POST">
					<div class="form-group">
						<label for="username">账号</label>
						<input type="text" class="form-control" name="username" value="" placeholder="账号" />
					</div>
					<div class="form-group">
						<label for="password">密码</label>
						<input type="password" class="form-control" name="password" placeholder="密码" />
					</div>
					<input type="submit" id="login" value="login" class="btn btn-primary" />
				</form>
		</div>
	</div>

</body>
</html>

2.批处理

2.1.1 批处理Spring Batch

Spring Batch是用来处理大量数据操作的一个框架,主要用来读取大量的数据,然后进行一定处理后输出成指定的形式

2.1.2 Spring Batch主要组成

JobRepository        :用来注册Job容器

JobLauncher          :用来启动Job的接口

Job                         :我们要实际执行的任务,包含一个或多个Step

Step                       :Step步骤包含ItemReader、ItemProcessor、ItemWriter

ItemReader           :读取数据的接口

ItemProcessor       :处理数据的接口

ItemWriter              :输出数据的接口

上述主要组成部分只需要注册成Spring的Bean即可。若想开启批处理的支持还需要在配置类上使用@EnableBatchProcessing

package com.xupeng.xupeng20191203.config;


import javax.sql.DataSource;

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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

import com.xupeng.xupeng20191203.domain.Person;

@Configuration
@EnableBatchProcessing
public class BatchConfig {
	@Bean
	public JobRepository jobRepository(DataSource dataSource,PlatformTransactionManager transactionManager) throws Exception{
		JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
		jobRepositoryFactoryBean.setDataSource(dataSource);
		jobRepositoryFactoryBean.setTransactionManager(transactionManager);
		jobRepositoryFactoryBean.setDatabaseType("oracle");
		return jobRepositoryFactoryBean.getObject();
	}
	
	@Bean
	public SimpleJobLauncher jobLauncher(DataSource dataSource,PlatformTransactionManager transactionManager) throws Exception{
		SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
		jobLauncher.setJobRepository(jobRepository(dataSource,transactionManager));
		return jobLauncher;
	}
	
	@Bean
	public org.springframework.batch.core.Job impJob(JobBuilderFactory jobs,Step s1){
		return jobs.get("importJob")
				.incrementer(new RunIdIncrementer())
				.flow(s1)
				.end()
				.build();
	}
	
	@Bean
	public Step step1(StepBuilderFactory stepBuilderFactory,ItemReader<Person> reader,ItemWriter<Person> writer,ItemProcessor<Person, Person> processor){
		return stepBuilderFactory
				.get("step1")
				.<Person,Person>chunk(65000)
				.reader(reader)
				.processor(processor)
				.writer(writer)
				.build();
	}
	
	@Bean
	public ItemReader<Person> reader(){
		return reader;
	}
	
	@Bean
	public ItemProcessor<Person, Person> processor(){
		return processor;
	}
	
	@Bean
	public ItemWriter<Person> writer(DataSource dataSource){
		return writer;
	}
}

2.1.3 Job监听

若需要监听我们的Job的执行情况,则定义一个类实现JobExecutionListener,并在定义Job的Bean上绑定该监听器

package com.xupeng.xupeng20191203.listener;

import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;

public class MyJobListener implements JobExecutionListener {

	@Override
	public void beforeJob(JobExecution jobExecution) {
		// TODO Auto-generated method stub
		//job开始前
	}	
	
	@Override
	public void afterJob(JobExecution jobExecution) {
		// TODO Auto-generated method stub
		//job开始后
	}
}
	@Bean
	public MyJobListener myJobListener(){
		return new MyJobListener();
	}

2.1.4 数据读取

Spring Batch为我们提供了大量的ItemReader的实现,用来读取不同的数据来源

2.1.5 数据处理及校验

数据处理和校验都要通过ItemProcess接口实现来完成

2.1.5.1 数据处理

数据处理只需要实现ItemProcess接口,重写其process方法。方法传入的参数是从ItemReader读取到的数据,返回的数据给ItemWriter

package com.xupeng.xupeng20191203.process;

import org.springframework.batch.item.ItemProcessor;

import com.xupeng.xupeng20191203.domain.Person;

public class MyItemProcess implements ItemProcessor<Person, Person> {
	@Override
	public Person process(Person person) throws Exception {
		String name = person.getName().toUpperCase();
		person.setName(name);
		return person;
	}
}

2.1.5.2 数据校验

我们以JSR-303的注解来校验ItemReader读取到的数据是否满足要求

首先实现ValidatingItemProcessor接口

package com.xupeng.xupeng20191203.process;

import org.springframework.batch.item.validator.ValidatingItemProcessor;
import org.springframework.batch.item.validator.ValidationException;

import com.xupeng.xupeng20191203.domain.Person;

public class MyItemProcess extends ValidatingItemProcessor<Person> {
	@Override
	public Person process(Person person) throws ValidationException {
		super.process(person);
		return person;
	}
}

定义校验器,实现的Validator接口来于Spring,使用JSR-303的Validator来校验

package com.xupeng.xupeng20191203.process;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;

import org.springframework.batch.item.validator.ValidationException;
import org.springframework.batch.item.validator.Validator;
import org.springframework.beans.factory.InitializingBean;

public class MyBeanValidator<T> implements Validator<T>,InitializingBean {
	private javax.validation.Validator validator;
	
	@Override
	public void afterPropertiesSet() throws Exception {
		ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
		validator = validatorFactory.usingContext().getValidator();
	}

	@Override
	public void validate(T value) throws ValidationException {
		Set<ConstraintViolation<T>> constraintViolations = validator.validate(value);
		if(constraintViolations.size()>0){
			StringBuilder message = new StringBuilder();
			for(ConstraintViolation<T> constraintViolation:constraintViolations){
				message.append(constraintViolation.getMessage()+"\n");
			}
			throw new ValidationException(message.toString());
		}
	}

}

在定义我们的MyItemProcessor时必须将MyBeanValidator设置进去

	@Bean
	public ItemProcessor<Person, Person> processor(){
		MyItemProcess process = new MyItemProcess();
		process.setValidator(myBeanValidator());
		return process;
	}

	public Validator<Person> myBeanValidator() {
		return new MyBeanValidator<Person>();
	}

2.1.6 数据输出

Spring Batch为我们提供了大量的ItemWriter的实现,用来将数据输出到不同的目的地

2.1.7 计划任务

Spring Batch的任务是通过JobLauncher的run方法来执行的,因此只需要在普通的计划任务方法中执行JobLauncher的run方法即可。不要忘记@EnableScheduling开启计划任务的支持

package com.xupeng.xupeng20191203.service;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class ScheduledTaskService {
	
	@Autowired
	JobLauncher jobLauncher;
	
	@Autowired
	Job impJob;
	
	public JobParameters jobParameters;
	
	@Scheduled(fixedRate=5000)
	public void execute() throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException{
		jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis()).toJobParameters();
		jobLauncher.run(impJob, jobParameters);
	}
	
}

2.1.8 参数后置设置

我们在ItemReader和ItemWriter的Bean在定义的时候,参数已经硬编码在Bean的初始化中

	@Bean
	public ItemReader<Person> reader(){
		FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
		reader.setResource(new ClassPathResource("people.csv"));
		return reader;
	}

若想实现参数后置绑定,我们可以在JobParameters中绑定参数,在Bean定义的时候用一个特殊的Bean生命周期注解@StepScope,然后通过@Value注入此参数

@Scheduled(fixedRate=5000)
	public void execute() throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException{
		String path = "people.csv";
		jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
				.addString("input.file.name", path)
				.toJobParameters();
		jobLauncher.run(impJob, jobParameters);
	}
@Bean
	@StepScope
	public ItemReader<Person> reader(@Value("#{jobParameters['input.file.name']}") String pathToFile){
		FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
		reader.setResource(new ClassPathResource(pathToFile));
		return reader;
	}

2.2 Spring Boot的支持

2.2.1 Spring Boot为我们自动初始化了Spring Batch存储批处理记录的数据库,且当我们程序启动时,会自动执行我们定义的Job的Bean

2.2.2 Spring Boot提供的对Spring Batch的属性

spring.batch.job.names=job1,job2  #启动时要执行的job,默认执行全部
spring.batch.job.enabled=true     #是否自动执行定义的Job,默认是
spring.batch.initializer.enabled=true    #是否初始化Spring Batch的数据库,默认是
spring.batch.schema=classpath:org/springframework/batch/core/schema-@@platform@@.sql      #指定SQL脚本的路径
spring.batch.table-prefix=BATCH_       #设置数据库表的前缀,默认是BATCH_ 开头。

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鹏哥哥啊Aaaa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值