观察者模式是一种定向监听模式,即针对特定的文件或者数据节点进行监听,根据监听数据的变化进行业务处理。
下面手写文件监听程序,以展示观察者模式流程。
1、启动观察者监听
@Component
public class FileListenerComponent {
private final Logger logger = LoggerFactory.getLogger(getClass());
@PostConstruct
private void register() {
try {
// 构造监听目录观察对象及配置自定义文件过滤
FileAlterationObserver observer = new FileAlterationObserver(
"D:/file/", new MyFileFilter());
// 构造监听类
FileListenerAdaptor listener = new FileListenerAdaptor();
// 为观察对象添加监听类
observer.addListener(listener);
// 配置监听操作类--监听时间3000毫秒
FileAlterationMonitor monitor = new FileAlterationMonitor(
3000,
new FileAlterationObserver[] { observer });
// 开始监听
monitor.start();
logger.info("监听开始" + DateUtil.getTime());
} catch (Exception e) {
// TODO: handle exception
logger.error("FileListenerComponent", e);
}
}
}
2、FileAlterationObserver文件变化监听-校验文件变化关键源码(以文件创建为例)
// 文件变化监听
private void checkAndNotify(FileEntry parent, FileEntry[] previous, File[] files) {
int c = 0;
FileEntry[] current = files.length > 0 ? new FileEntry[files.length] : FileEntry.EMPTY_ENTRIES;
for (FileEntry entry : previous) {
while (c < files.length && comparator.compare(entry.getFile(), files[c]) > 0) {
current[c] = createFileEntry(parent, files[c]);
doCreate(current[c]);
c++;
}
if (c < files.length && comparator.compare(entry.getFile(), files[c]) == 0) {
doMatch(entry, files[c]);
checkAndNotify(entry, entry.getChildren(), listFiles(files[c]));
current[c] = entry;
c++;
} else {
checkAndNotify(entry, entry.getChildren(), FileUtils.EMPTY_FILE_ARRAY);
doDelete(entry);
}
}
for (; c < files.length; c++) {
current[c] = createFileEntry(parent, files[c]);
doCreate(current[c]);
}
parent.setChildren(current);
}
// 文件创建
private void doCreate(FileEntry entry) {
for (FileAlterationListener listener : listeners) {
if (entry.isDirectory()) {
listener.onDirectoryCreate(entry.getFile());
} else {
listener.onFileCreate(entry.getFile());
}
}
FileEntry[] children = entry.getChildren();
for (FileEntry aChildren : children) {
doCreate(aChildren);
}
}
3、FileAlterationListener根据文件监听结果进行业务处理--ftp上传本地文件到ftp服务器
@Override
public void onFileCreate(File file) {
super.onFileCreate(file);
logger.info("onFileCreate:" + file.getName());
// 文件路径
String filePath = file.getPath().replace("\\", "/")
.replace(Const.TASK_PATH, "");
// 文件名称
String fileName = file.getName();
try {
FtpTools.uploadFile(filePath.replaceAll(fileName, ""), fileName,
new FileInputStream(file));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
logger.error("上传失败", e);
}
}
4、总结
该模式核心在于监听,另外一个典型的观察者模式为消息队列,消费者通过监听队列数据,从消费者中取数据并进行业务处理。