Java NIO или Java New I/O это крайне полезный пакет, позволяющий использовать асинхронный ввод/вывод. Сегодня с помощью java.nio.file , следуя паттерну Observer , мы реализуем свой класс для наблюдения за состоянием файлов в папке. Наш план:
- Первым делом создадим WatchService.
- Потом переменную Path , указывающую на папку, которую планируем мониторить.
- Далее бесконечный цикл наблюдения. Когда происходит интересующее нас событие, класс WathKey помещает его в очередь наблюдателя. После обработки события мы должны вернуть ключ в состояние готовности, вызвав метод reset() . Если метод вернёт false , то ключ больше не действителен, цикл можно завершить.
Данный код должен вывести в консоль следующее:
Watch Service API довольно низкоуровневая штука, мы реализуем на его основе свой более высокоуровневый API. Начнём с написания класса FileEvent . Так как это объект состояния события, его необходимо унаследовать от EventObject и передать в конструктор ссылку на файл, за котором будем наблюдать.
Теперь создаём интерфейс слушателя FileListener , наследуемый от java.util.EventListener . Этот интерфейс должны реализовать все слушатели, которые будут подписываться на события нашей папки.
Наконец, создаём класс, который будет хранить в себе список слушателей, подписанных на папку. Назовём его FileWatcher .
Хорошей идеей будет реализовать класс FileWatcher как Runnable , чтобы иметь возможность запускать наблюдение в виде демона, если указанная папка существует.
Так как в методе run() будут создаваться объекты WatchService , использующие внешние ресурсы (ссылки на файлы), все события будем хранить в статическом списке. Такая реализация позволит вызвать метод close() из любого потока, ждущего ключ. А также вызвать исключение ClosedWatchServiceException , чтобы отменить наблюдение без утечки памяти.
Когда происходит интересующее нас событие и путь корректен, мы уведомляем слушателей о событии. Если была создана новая директория, то для неё будет инициализирован новый экземпляр FileWatcher .
Полная реализация класса FileWatcher будет выглядеть так:
Последний штрих – создание класса FileAdapter , простейшей реализации интерфейса FileListener .
Чтобы убедиться в работоспособности написанного кода, можно использовать несложный класс FileWatcherTest .
Несмотря на кажущуюся простоту, наблюдатели – мощный инструмент автоматизации процессов. С помощью них, например, можно автоматически перезапускать скрипты на продакшене, если один из них был изменён. Уменьшение человеческого фактора – благо для программиста.
А используете ли вы наблюдателей в своей работе? Или, может быть, реактивное программирование?