如何在 Web 容器中使用 Spring 批处理获取 @Postconstruct?

Posted

技术标签:

【中文标题】如何在 Web 容器中使用 Spring 批处理获取 @Postconstruct?【英文标题】:How to get @Postconstruct with Spring batch in web container? 【发布时间】:2018-01-04 23:25:19 【问题描述】:

目前,我正在尝试使用文档 https://docs.spring.io/spring-batch/reference/html/configureJob.html 中用于 spring-batch-boot 的基本 Web 容器指南,让我的脚本在 tomcat 服务器上运行 在修改主类之前,该脚本作为 jar 文件正常工作,但是当我尝试将其转换为 servlet 时,我的 @PostConstruct 仅在服务器启动时出现问题。此代码将 application.properties 设置为 spring.batch.job.enabled=false 并有一个控制器

@Controller
public class JobLauncherController 
   @Autowired
   JobLauncher jobLauncher;

   @Autowired
   Job job;

   @RequestMapping("/jobLauncher.html")
   public void handle() throws Exception
      jobLauncher.run(job, new JobParameters());

以主Application为tomcat启动servlet为

@SpringBootApplication
@EnableBatchProcessing
public class BatchApplication extends SpringBootServletInitializer

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) 
    return application.sources(BatchApplication.class);


public static void main(String[] args) 

    SpringApplication.run(BatchApplication.class, args);


问题是我的工作使用自定义项目读取器和编写器在使用@PostConstruct 运行它之前对其进行初始化。它在服务器启动时运行 @PostConstruct,这有助于初始化 bean 以进行写入。 我的项目阅读器/编写器看起来像这样

public class CustomReader extends ItemStreamSupport implements ItemReader<Acct>, ResourceAwareItemReaderItemStream<Acct> 
    //basic autowiring
    private int nextAcctIndex;
    private List<Acct> acctsList = new ArrayList();

    @PostConstruct
    private void initialize() throws IOException 
        //logic to parse files
        acctsList = Collections.unmodifiableList(acctsList);
        nextAcctIndex = 0;
    

    @Override
    public Acct read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException 
        // System.out.println("Start Read");

        Acct nextAcct = null;
        if (nextAcctIndex < acctsList.size()) 
            nextAcct = acctsList.get(nextAcctIndex);
            nextAcctIndex++;
            //System.out.println(nextAcct);
        

与大多数示例一样,BatchConfiguration 将所有内容调用为@Bean public IteamReader<Acct> CustomReader() return new CustomReader();

我的问题是我是否以错误的方式处理这个问题,或者有没有办法让它只有在控制器请求时才能调用 @PostConstruct

【问题讨论】:

你的读者/作者应该是步骤或工作范围。显然,您将它们创建为单例。但是你为什么要在@PostConstruct 方法中这样做呢?没有这种需要…… 你想用@PostConstruct做什么?为什么要使用它而不是常规的 spring 注释? 就是这样。我是 spring 新手,不确定我到底想问什么,但 StepExecutionListener 与 BeforeStep 和 AfterStep 完美搭配 【参考方案1】:

你需要使用

@BeforeStep
public void beforeStep(StepExecution stepExecution) 
    init();

@PostConstruct 用于在applicationContext 加载后初始化一次。 在您的情况下,您希望在每次作业运行时都运行此初始化(您不希望数据在不同的作业之间泄漏,对吗?)

【讨论】:

以上是关于如何在 Web 容器中使用 Spring 批处理获取 @Postconstruct?的主要内容,如果未能解决你的问题,请参考以下文章

如何在web项目中配置Spring的Ioc容器

spring之如何在web应用中使用?

spring源码:web容器启动(li)

如何让spring mvc web应用启动时就执行特定处理

Spring Boot使用嵌入式容器,自定义Filter如何配置?

Spring_在 WEB 应用中使用