En guide til WatchService i Java NIO2

1. Oversigt

I denne artikel skal vi udforske WatchService interface til Java NIO.2 filsystem API'er. Dette er en af ​​de mindre kendte funktioner i de nyere IO API'er, der blev introduceret i Java 7 ved siden af FileVisitor interface.

At bruge WatchService interface i dine applikationer, skal du importere de relevante klasser:

import java.nio.file. *;

2. Hvorfor bruge WatchService

Et almindeligt eksempel for at forstå, hvad tjenesten gør, er faktisk IDE.

Du har måske bemærket, at IDE'erne altid registrerer en ændring i kildekodefiler der sker uden for sig selv. Nogle IDE'er informerer dig ved hjælp af en dialogboks, så du kan vælge at genindlæse filen fra filsystemet eller ikke, andre opdaterer blot filen i baggrunden.

På samme måde gør nyere rammer som Play også varm genindlæsning af applikationskoden som standard - hver gang du udfører redigeringer fra en hvilken som helst editor.

Disse applikationer anvender en funktion kaldet meddelelse om filændring der er tilgængelig i alle filsystemer.

I bund og grund, vi kan skrive kode for at afstemme filsystemet for ændringer i specifikke filer og mapper. Denne løsning er dog ikke skalerbar, især hvis filerne og katalogerne når hundreder og tusinder.

I Java 7 NIO.2 er WatchService API giver en skalerbar løsning til overvågning af mapper for ændringer. Det har en ren API og er så godt optimeret til ydeevne, at vi ikke behøver at implementere vores egen løsning.

3. Hvordan fungerer Watchservice?

At bruge WatchService funktioner, er det første skridt at oprette en WatchService eksempel ved hjælp af java.nio.file.FileSystems klasse:

WatchService watchService = FileSystems.getDefault (). NewWatchService ();

Dernæst skal vi oprette stien til den mappe, vi vil overvåge:

Sti sti = Paths.get ("pathToDir");

Efter dette trin skal vi registrere stien hos urtjenesten. Der er to vigtige begreber at forstå på dette stadium. Det StandardWatchEventKinds klasse og WatchKey klasse. Se på følgende registreringskode for at forstå, hvor hvert fald falder. Vi følger dette med forklaringer på det samme:

WatchKey watchKey = path.register (watchService, StandardWatchEventKinds ...);

Bemærk kun to vigtige ting her: For det første tager stieregistrerings-API-opkaldet uretjenesteinstansen som den første parameter efterfulgt af variable argumenter for StandardWatchEventKinds. For det andet er returtypen for registreringsprocessen en WatchKey eksempel.

3.1. Det StandardWatchEventKinds

Dette er en klasse, hvis forekomster fortæller urtjenesten, hvilke slags begivenheder der skal overvåges i det registrerede bibliotek. Der er i øjeblikket fire mulige begivenheder at se på:

  • StandardWatchEventKinds.ENTRY_CREATE - udløses, når der oprettes en ny post i det overvågede bibliotek. Det kan skyldes oprettelsen af ​​en ny fil eller omdøbning af en eksisterende fil.
  • StandardWatchEventKinds.ENTRY_MODIFY - udløses, når en eksisterende post i det overvågede bibliotek ændres. Alle filredigeringer udløser denne begivenhed. På nogle platforme vil selv ændring af filattributter udløse det.
  • StandardWatchEventKinds.ENTRY_DELETE - udløses, når en post slettes, flyttes eller omdøbes i det overvågede bibliotek.
  • StandardWatchEventKinds.OVERFLOW - udløst for at angive mistede eller kasserede begivenheder. Vi vil ikke fokusere meget på det

3.2. Det WatchKey

Denne klasse repræsenterer registreringen af ​​et bibliotek hos urtjenesten. Dets forekomst returneres til os af overvågningstjenesten, når vi registrerer et bibliotek, og når vi spørger overvågningstjenesten, om der er sket nogen begivenheder, vi har registreret.

Watch-tjenesten giver os ingen tilbagekaldsmetoder, der kaldes, hver gang en begivenhed finder sted. Vi kan kun afstemme det på en række måder for at finde disse oplysninger.

Vi kan bruge afstemning API:

WatchKey watchKey = watchService.poll ();

Dette API-opkald vender straks tilbage. Den returnerer den næste ur-nøgle i kø, hvis begivenheder har fundet sted eller nul, hvis der ikke er registreret nogen begivenheder.

Vi kan også bruge en overbelastet version, der tager en tiden er gået argument:

WatchKey watchKey = watchService.poll (lang timeout, TimeUnit enheder);

Dette API-opkald svarer til det forrige i returværdi. Det blokerer dog for tiden er gået tidsenheder for at give mere tid inden for hvilken en begivenhed kan forekomme i stedet for at returnere null med det samme.

Endelig kan vi bruge tage API:

WatchKey watchKey = watchService.take ();

Denne sidste tilgang blokerer simpelthen, indtil en begivenhed finder sted.

Vi skal bemærke noget meget vigtigt her: når WatchKey forekomst returneres af en af afstemning eller tage API'er, det fanger ikke flere begivenheder, hvis det nulstilles API ikke påberåbes:

watchKey.reset ();

Dette betyder, at forekomsten af ​​urnøglen fjernes fra uretjenestekøen, hver gang den returneres af en afstemning. Det Nulstil API-opkald sætter det tilbage i køen for at vente på flere begivenheder.

Den mest praktiske anvendelse af seertjenesten vil kræve en sløjfe, inden for hvilken vi løbende kontrollerer for ændringer i den overvågede mappe og behandler i overensstemmelse hermed. Vi kan bruge følgende udtryk til at implementere dette:

WatchKey-tast; mens ((key = watchService.take ())! = null) {for (WatchEvent event: key.pollEvents ()) {// process} key.reset (); }

Vi opretter en urnøgle til at gemme returværdien af ​​afstemningsoperationen. While-sløjfen blokerer, indtil den betingede erklæring vender tilbage med enten en urnøgle eller nul.

Når vi får en urnøgle, udfører while-løkken koden inde i den. Vi bruger WatchKey.pollEvents API for at returnere en liste over begivenheder, der har fundet sted. Vi bruger derefter en for hver loop for at behandle dem en efter en.

Når alle begivenheder er behandlet, skal vi ringe til Nulstil API til at omslutte urnøglen igen.

4. Eksempel på katalogovervågning

Da vi har dækket WatchService API i det foregående afsnit, og hvordan det fungerer internt, og hvordan vi kan bruge det, kan vi nu gå videre og se på et komplet og praktisk eksempel.

Af bærbarhedsårsager skal vi se efter aktivitet i brugerens hjemmekatalog, som skal være tilgængelig på alle moderne operativsystemer.

Koden indeholder kun få linier kode, så vi beholder den bare i hovedmetoden:

public class DirectoryWatcherExample {public static void main (String [] args) {WatchService watchService = FileSystems.getDefault (). newWatchService (); Sti sti = Paths.get (System.getProperty ("user.home")); path.register (watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); WatchKey-tast; mens ((key = watchService.take ())! = null) {for (WatchEvent event: key.pollEvents ()) {System.out.println ("Hændelsestype:" + event.kind () + ". Berørt fil : "+ event.context () +". "); } key.reset (); }}}

Og det er alt, hvad vi virkelig skal gøre. Nu kan du køre klassen for at begynde at se en mappe.

Når du navigerer til brugerens hjemmebibliotek og udfører enhver filmanipuleringsaktivitet som at oprette en fil eller bibliotek, ændre indholdet af en fil eller endda slette en fil, bliver det hele logget på konsollen.

For eksempel forudsat at du går til brugerens hjem, skal du højreklikke i rummet og vælge 'ny -> fil` for at oprette en ny fil og derefter navngive den testFile. Derefter tilføjer du noget indhold og gemmer. Udgangen på konsollen vil se sådan ud:

Begivenhedstype: ENTRY_CREATE. Berørt fil: Nyt tekstdokument.txt. Begivenhedstype: ENTRY_DELETE. Berørt fil: Nyt tekstdokument.txt. Begivenhedstype: ENTRY_CREATE. Berørt fil: testFile.txt. Begivenhedstype: ENTRY_MODIFY. Berørt fil: testFile.txt. Begivenhedstype: ENTRY_MODIFY. Berørt fil: testFile.txt.

Du er velkommen til at redigere stien for at pege på et hvilket som helst bibliotek, du vil se.

5. Konklusion

I denne artikel har vi udforsket nogle af de mindre almindeligt anvendte funktioner, der er tilgængelige i Java 7 NIO.2 - filsystem-API'er, især WatchService interface.

Vi har også formået at gennemgå trinnene til at opbygge et biblioteksapplikationsprogram for at demonstrere funktionaliteten.

Og som altid er den fulde kildekode til eksemplerne i denne artikel tilgængelig i Github-projektet.