WatchEventType.DELETE 好像不行
WatchEventType.DELETE doesn't seem to work
我想做的是跟踪删除的文件并围绕此应用某些逻辑(获取 ID 并更新实体)。我发现我们可以在通道适配器中传递一个监视事件列表,包括
FileReadingMessageSource.WatchEventType.DELETE
但是当我从文件夹中删除文件时,我没有看到任何事件被触发,并且转换器从未被应用
@Bean
public IntegrationFlow integrationFlow(FileToMovieTransformer fileToMovieTransformer) {
return this.integrationFlowBuilder()
.transform(fileToMovieTransformer)
.channel(movieHandlerChannel())
.get();
}
private IntegrationFlowBuilder integrationFlowBuilder() {
return IntegrationFlows.from(
Files.inboundAdapter(new File(localFilmFolder))
.autoCreateDirectory(true)
.useWatchService(true)
.watchEvents(FileReadingMessageSource.WatchEventType.CREATE, FileReadingMessageSource.WatchEventType.DELETE)
.patternFilter("*.xml"),
e -> e.poller(Pollers.fixedDelay(10, TimeUnit.SECONDS)
));
}
我会说你对待 DELETE
的方式不对:
/**
* Directory entry deleted.
*
* <p> When a directory is registered for this event then the {@link WatchKey}
* is queued when it is observed that an entry is deleted or renamed out of
* the directory. The event {@link WatchEvent#count count} for this event
* is always {@code 1}.
*/
public static final WatchEvent.Kind<Path> ENTRY_DELETE =
new StdWatchEventKind<Path>("ENTRY_DELETE", Path.class);
因此,已经没有任何消息可以作为消息发送到下游。我们这里肯定谈了一个FileReadingMessageSource
。但是有了 DELETE
就没有什么可读的了。我错过了什么吗?
这是目前文档中的内容:
The ENTRY_DELETE
events have effect for the ResettableFileListFilter
implementations and, therefore, their files
are provided for the remove()
operation.
This means that (when this event is enabled), filters such as the AcceptOnceFileListFilter
will have the file removed,
meaning that, if a file with the same name appears, it will pass the filter and be sent as a message.
因此,为了在发生 DELETE
事件时实现您想做的任何事情,您需要实现 ResettableFileListFilter
并且与 SimplePatternFileListFilter
一起,您应该将它们组合到 CompositeFileListFilter
.
删除文件时,会发出 DELETE
事件,我们最终得到如下逻辑:
if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) {
if (getFilter() instanceof ResettableFileListFilter) {
((ResettableFileListFilter<File>) getFilter()).remove(file);
}
其中提到的 CompositeFileListFilter
肯定实现了这个 ResettableFileListFilter
并将委托给您自己的实现。
感谢@Artem,这是完整的代码示例,似乎对我来说效果很好
private IntegrationFlowBuilder integrationFlowBuilder() {
final List<FileListFilter<File>> defaultFilters = new ArrayList<>(2);
defaultFilters.add(new IgnoreHiddenFileListFilter());
defaultFilters.add(new AcceptOnceFileListFilter<>());
defaultFilters.add(new SimplePatternFileListFilter("*.xml"));
defaultFilters.add(myCustomRemovalFilter);
CompositeFileListFilter fileListFilter = new CompositeFileListFilter<>(defaultFilters);
return IntegrationFlows.from(
Files.inboundAdapter(new File(localFilmFolder))
.autoCreateDirectory(true)
.filter(fileListFilter)
.useWatchService(true)
.watchEvents(FileReadingMessageSource.WatchEventType.CREATE, FileReadingMessageSource.WatchEventType.DELETE),
e -> e.poller(Pollers.fixedDelay(10, TimeUnit.SECONDS)
));
}
过滤器看起来像
@Component
public class MyCustomRemovalFilter implements ResettableFileListFilter<File> {
private static final Logger LOGGER = LogManager.getLogger(MyCustomRemovalFilter.class);
@Override
public boolean remove(File xmlFile) {
if (xmlFile == null) {
return true;
}
// TODO you own on removal logic
}
@Override
public List<File> filterFiles(File[] files) {
if (files == null || files.length == 0) {
return Collections.emptyList();
}
return Arrays.asList(files);
}
}
我想做的是跟踪删除的文件并围绕此应用某些逻辑(获取 ID 并更新实体)。我发现我们可以在通道适配器中传递一个监视事件列表,包括
FileReadingMessageSource.WatchEventType.DELETE
但是当我从文件夹中删除文件时,我没有看到任何事件被触发,并且转换器从未被应用
@Bean
public IntegrationFlow integrationFlow(FileToMovieTransformer fileToMovieTransformer) {
return this.integrationFlowBuilder()
.transform(fileToMovieTransformer)
.channel(movieHandlerChannel())
.get();
}
private IntegrationFlowBuilder integrationFlowBuilder() {
return IntegrationFlows.from(
Files.inboundAdapter(new File(localFilmFolder))
.autoCreateDirectory(true)
.useWatchService(true)
.watchEvents(FileReadingMessageSource.WatchEventType.CREATE, FileReadingMessageSource.WatchEventType.DELETE)
.patternFilter("*.xml"),
e -> e.poller(Pollers.fixedDelay(10, TimeUnit.SECONDS)
));
}
我会说你对待 DELETE
的方式不对:
/**
* Directory entry deleted.
*
* <p> When a directory is registered for this event then the {@link WatchKey}
* is queued when it is observed that an entry is deleted or renamed out of
* the directory. The event {@link WatchEvent#count count} for this event
* is always {@code 1}.
*/
public static final WatchEvent.Kind<Path> ENTRY_DELETE =
new StdWatchEventKind<Path>("ENTRY_DELETE", Path.class);
因此,已经没有任何消息可以作为消息发送到下游。我们这里肯定谈了一个FileReadingMessageSource
。但是有了 DELETE
就没有什么可读的了。我错过了什么吗?
这是目前文档中的内容:
The
ENTRY_DELETE
events have effect for theResettableFileListFilter
implementations and, therefore, their files are provided for theremove()
operation. This means that (when this event is enabled), filters such as theAcceptOnceFileListFilter
will have the file removed, meaning that, if a file with the same name appears, it will pass the filter and be sent as a message.
因此,为了在发生 DELETE
事件时实现您想做的任何事情,您需要实现 ResettableFileListFilter
并且与 SimplePatternFileListFilter
一起,您应该将它们组合到 CompositeFileListFilter
.
删除文件时,会发出 DELETE
事件,我们最终得到如下逻辑:
if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) {
if (getFilter() instanceof ResettableFileListFilter) {
((ResettableFileListFilter<File>) getFilter()).remove(file);
}
其中提到的 CompositeFileListFilter
肯定实现了这个 ResettableFileListFilter
并将委托给您自己的实现。
感谢@Artem,这是完整的代码示例,似乎对我来说效果很好
private IntegrationFlowBuilder integrationFlowBuilder() {
final List<FileListFilter<File>> defaultFilters = new ArrayList<>(2);
defaultFilters.add(new IgnoreHiddenFileListFilter());
defaultFilters.add(new AcceptOnceFileListFilter<>());
defaultFilters.add(new SimplePatternFileListFilter("*.xml"));
defaultFilters.add(myCustomRemovalFilter);
CompositeFileListFilter fileListFilter = new CompositeFileListFilter<>(defaultFilters);
return IntegrationFlows.from(
Files.inboundAdapter(new File(localFilmFolder))
.autoCreateDirectory(true)
.filter(fileListFilter)
.useWatchService(true)
.watchEvents(FileReadingMessageSource.WatchEventType.CREATE, FileReadingMessageSource.WatchEventType.DELETE),
e -> e.poller(Pollers.fixedDelay(10, TimeUnit.SECONDS)
));
}
过滤器看起来像
@Component
public class MyCustomRemovalFilter implements ResettableFileListFilter<File> {
private static final Logger LOGGER = LogManager.getLogger(MyCustomRemovalFilter.class);
@Override
public boolean remove(File xmlFile) {
if (xmlFile == null) {
return true;
}
// TODO you own on removal logic
}
@Override
public List<File> filterFiles(File[] files) {
if (files == null || files.length == 0) {
return Collections.emptyList();
}
return Arrays.asList(files);
}
}