Java 如何确保MultiResourceItemReader在每次执行作业时刷新资源

Java 如何确保MultiResourceItemReader在每次执行作业时刷新资源,java,spring,scheduled-tasks,task,Java,Spring,Scheduled Tasks,Task,我有一个java应用程序,它利用spring任务调度和批处理作业。我依靠job中的MultiResourceItemReader从目录中读取一些文件,处理它们,然后删除这些文件。外部进程负责定期将新文件放入该目录。但问题是,每次运行作业时,它都会尝试读取启动应用程序时存在的相同文件资源,因此失败,因为这些资源已经消失,而现在又有了新文件 问题是,如何配置应用程序,以便针对给定作业的每次计划执行评估resources属性 相关的豆子粘贴在下面: <bean id="multiResour

我有一个java应用程序,它利用spring任务调度和批处理作业。我依靠
job
中的
MultiResourceItemReader
从目录中读取一些文件,处理它们,然后删除这些文件。外部进程负责定期将新文件放入该目录。但问题是,每次运行
作业时,它都会尝试读取启动应用程序时存在的相同文件资源,因此失败,因为这些资源已经消失,而现在又有了新文件

问题是,如何配置应用程序,以便针对给定
作业的每次计划执行评估resources属性

相关的豆子粘贴在下面:

  <bean id="multiResourceReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
    <property name="resources" value="file:/opt/data/*.csv" />
    <property name="delegate" ref="testFlatFileItemReader" />
  </bean>

  <batch:job id="MyJob">
    <batch:step id="readandstore">
      <batch:tasklet>
        <batch:chunk reader="multiResourceReader" writer="oracleItemWriter" commit-interval="10" />
      </batch:tasklet>
    </batch:step>
  </batch:job>

  <bean id="runScheduler" class="com.myapp.Scheduler">
    <property name="jobLauncher" ref="jobLauncher" />
    <property name="job" ref="MyJob" />
  </bean>

  <task:scheduled-tasks>
    <task:scheduled ref="runScheduler" method="run" cron="*/30 * * * * *" />
  </task:scheduled-tasks>

我设法解决了我自己发布的问题,因为几乎一周没有收到任何回复

我删除了
multiResourceReader
的resources属性,并在
下的侦听器中添加了一个
StepListener
,该侦听器实现了
StepExecutionListener
。此侦听器有两个方法,一个在步骤执行之前调用,另一个在步骤执行之后调用。
StepListener
接受一个名为
filePattern
的属性,该属性的值类似于您以前为
multiResourceReader
的resources属性提供的值。以下是更新后的bean的外观:

  <batch:job id="MyJob">
    <batch:step id="readandstore">
      <batch:tasklet>
        <batch:chunk reader="multiResourceReader" writer="oracleItemWriter" commit-interval="10" />
        <batch:listeners>
          <batch:listener ref="StepListener" />
        </batch:listeners>
      </batch:tasklet>
    </batch:step>
  </batch:job>

  <bean id="multiResourceReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
    <property name="delegate" ref="csvFileItemReader" />
  </bean>

  <bean id="StepListener" class="com.myapp.StepListener">
    <property name="filePattern" value="file:/opt/data/*.csv" />
  </bean>

bean multiResourceReader的作用域是单例的,因此每个作用域只创建1个。当这个bean被创建时,资源的价值就被解析了

如果您将bean multiResourceReader的作用域设置为step,那么它也应该解决您的问题。然后每次执行步骤时都会创建一个新bean。

尝试在名为“multiResourceReader”的配置bean中添加标记“step”:


我也遇到过同样的问题,但我用另一种方法解决了,可能会有帮助,我正在使用FlatFileItemReader,但问题是一样的

解决方案是使用属性资源中的ref和处理jobParams的bean,这样每次步骤重新开始时,它都是一个新实例,具有新值,下面的代码就是我如何执行的:

<bean id="customFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<property name="resource" ref="customFile"/><!-- avoid use directly jobParams here -->
<property name="linesToSkip" value="0" />
<property name="encoding" value="ISO-8859-1" />
<property name="comments" value="*, \u001A" />
<property name="lineMapper">
    <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
        <property name="lineTokenizer">
            <bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                <property name="delimiter" value=";" />
            </bean>
        </property>
        <property name="fieldSetMapper">
            <bean class="br.com.sample.batch.CustomFieldSetMapperSIAW"/>
        </property>
    </bean>
</property>



另一个选项是在调用
super.open()
方法之前,扩展
MultiResourceItemReader
并重写
open()
方法并调用
setResources()

public class CustomMultiItemReader<T> extends MultiResourceItemReader<T> {
    private static final Log logger = LogFactory.getLog(PrestoMultiItemReader.class);
    
    private String filePattern;

    public CustomMultiItemReader() {
        super();
    }

    @Override
    public void open(ExecutionContext executionContext) {
        Assert.notNull(filePattern, "filePattern must be set");
        try {
            ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = patternResolver.getResources(filePattern);
            super.setResources(resources);
        } catch (IOException e) {
            logger.error("No resources to read.", e);
        }
        super.open(executionContext);
    }

    public void setFilePattern(String filePattern) {
        this.filePattern = filePattern;
    }
}

我发现这确实是真的,但是您需要将资源定义为显式属性,如果您使用“p”名称空间定义资源属性,那么即使bean是步骤范围的,也不会重新加载资源。
<bean id="customFile" class="org.springframework.core.io.FileSystemResource" scope="step">
<constructor-arg value="#{jobParameters[arquivoGSIN]}"></constructor-arg>
public class CustomMultiItemReader<T> extends MultiResourceItemReader<T> {
    private static final Log logger = LogFactory.getLog(PrestoMultiItemReader.class);
    
    private String filePattern;

    public CustomMultiItemReader() {
        super();
    }

    @Override
    public void open(ExecutionContext executionContext) {
        Assert.notNull(filePattern, "filePattern must be set");
        try {
            ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = patternResolver.getResources(filePattern);
            super.setResources(resources);
        } catch (IOException e) {
            logger.error("No resources to read.", e);
        }
        super.open(executionContext);
    }

    public void setFilePattern(String filePattern) {
        this.filePattern = filePattern;
    }
}
public CustomMultiItemReader<T> customMultiItemReader() {
    String filePattern = "file:/...";
    CustomMultiItemReader<T> reader = new CustomMultiItemReader<T>();
    reader.setDelegate(reader()); //reader to delegate here
    reader.setFilePattern(filePattern);
    reader.setStrict(true); 
    return reader;
}