Oversikt over Java Naming and Directory Interface
1. Introduksjon
Java Naming and Directory Interface (JNDI) gir jevn bruk av navngivning og / eller katalogtjenester som Java API. Dette grensesnittet kan brukes til å binde objekter, slå opp eller spørre objekter, samt oppdage endringer på de samme objektene.
Mens JNDI-bruk inkluderer en variert liste over støttede navngivnings- og katalogtjenester, vil vi i denne opplæringen fokusere på JDBC mens vi utforsker JNDIs API.
2. JNDI Beskrivelse
Alt arbeid med JNDI krever en forståelse av den underliggende tjenesten i tillegg til en tilgjengelig implementering. For eksempel krever en databasetilkoblingstjeneste spesifikke egenskaper og unntakshåndtering.
Imidlertid frakobler JNDIs abstraksjon tilkoblingskonfigurasjonen fra applikasjonen.
La oss utforske Navn og Kontekst, som inneholder kjernefunksjonaliteten til JNDI.
2.1. Navn Grensesnitt
Navn objectName = new CompositeName ("java: comp / env / jdbc");
De Navn grensesnitt gir muligheten til å administrere komponentnavn og syntaks for JNDI-navn. Det første token av strengen representerer den globale konteksten, etter at hver streng lagt til representerer neste underkontekst:
Oppregningselementer = objectName.getAll (); mens (elements.hasMoreElements ()) {System.out.println (elements.nextElement ()); }
Produksjonen vår ser ut som:
java: comp env jdbc
Som vi kan se, / er avgrenseren for Navn underkontekster. La oss nå legge til en underkontekst:
objectName.add ("eksempel");
Så tester vi vårt tillegg:
assertEquals ("eksempel", objectName.get (objectName.size () - 1));
2.2. Kontekst Grensesnitt
Kontekst inneholder egenskapene for navngivning og katalogtjeneste. Her, la oss bruke litt hjelpekode fra våren for enkelhets skyld for å bygge en Kontekst:
SimpleNamingContextBuilder builder = ny SimpleNamingContextBuilder (); builder.activate ();
Vårens SimpleNamingContextBuilder oppretter en JNDI-leverandør og aktiverer deretter byggherren med NamingManager:
JndiTemplate jndiTemplate = ny JndiTemplate (); ctx = (InitialContext) jndiTemplate.getContext ();
Endelig, JndiTemplate hjelper oss med å få tilgang til InitialContext.
3. JNDI Objektbinding og oppslag
Nå som vi har sett hvordan du bruker Navn og Kontekst, la oss bruke JNDI til å lagre en JDBC Datakilde:
ds = ny DriverManagerDataSource ("jdbc: h2: mem: mydb");
3.1. Bindende JNDI-objekter
Da vi har en sammenheng, la oss binde objektet til det:
ctx.bind ("java: comp / env / jdbc / datasource", ds);
Generelt sett skal tjenester lagre en objektreferanse, serialiserte data eller attributter i en katalogkontekst. Alt avhenger av applikasjonens behov.
Merk at bruk av JNDI på denne måten er mindre vanlig. Vanligvis grensesnitt JNDI med data som administreres utenfor applikasjonens kjøretid.
Imidlertid, hvis applikasjonen allerede kan opprette eller finne den Datakilde, det kan være lettere å koble den med våren. I kontrast, hvis noe utenfor applikasjonen vår bundet objekter i JNDI, kan applikasjonen konsumere dem.
3.2. Slå opp JNDI-objekter
La oss slå opp vår Datakilde:
DataSource ds = (DataSource) ctx.lookup ("java: comp / env / jdbc / datasource");
Og så la oss teste for å sikre det Datakilde er som forventet:
assertNotNull (ds.getConnection ());
4. Vanlige JNDI-unntak
Arbeid med JNDI kan noen ganger føre til unntak for kjøretid. Her er noen vanlige.
4.1. NameNotFoundException
ctx.lookup ("badJndiName");
Siden dette navnet ikke er bundet i denne sammenhengen, ser vi dette stabelsporet:
javax.naming.NameNotFoundException: Navn [badJndiName] ikke bundet; 0 bindinger: [] på org.springframework.mock.jndi.SimpleNamingContext.lookup (SimpleNamingContext.java:140) på java.naming / javax.naming.InitialContext.lookup (InitialContext.java:409)
Vi bør merke oss at stabelsporingen inneholder alle objekter bundet, noe som er nyttig for å spore hvorfor unntaket skjedde.
4.2. NoInitialContextException
Ethvert samspill med InitialContext kan kaste NoInitialContextException:
assertThrows (NoInitialContextException.class, () -> {JndiTemplate jndiTemplate = new JndiTemplate (); InitialContext ctx = (InitialContext) jndiTemplate.getContext (); ctx.lookup ("java: comp / env / jdbc /) source" .printStackTrace ();
Vi bør merke oss at denne bruken av JNDI er gyldig, slik vi brukte den tidligere. Denne gangen er det imidlertid ingen JNDI-kontekstleverandør, og et unntak vil bli kastet:
javax.naming.NoInitialContextException: Trenger du å angi klassenavn i miljø eller systemegenskap, eller i en applikasjonsressursfil: java.naming.factory.initial på java.naming / javax.naming.spi.NamingManager.getInitialContext (NamingManager.java: 685)
5. Rollen til JNDI i moderne applikasjonsarkitektur
Samtidig som JNDI spiller mindre rolle i lette, containeriserte Java-applikasjoner som Spring Boot, er det andre bruksområder. Tre Java-teknologier som fremdeles bruker JNDI er JDBC, EJB og JMS. Alle har et bredt spekter av bruksområder på tvers av Java-applikasjoner.
For eksempel kan et eget DevOps-team administrere miljøvariabler som brukernavn og passord for en sensitiv databasetilkobling i alle miljøer. En JNDI-ressurs kan opprettes i webapplikasjonsbeholderen, med JNDI brukt som et lag med jevn abstraksjon som fungerer i alle miljøer.
Dette oppsettet lar utviklere lage og kontrollere en lokal definisjon for utviklingsformål mens de kobler til sensitive ressurser i et produksjonsmiljø gjennom det samme JNDI-navnet.
6. Konklusjon
I denne opplæringen så vi å koble til, binde og slå opp et objekt ved hjelp av Java Naming and Directory Interface. Vi så også på de vanlige unntakene som JNDI kastet.
Til slutt så vi på hvordan JNDI passer inn i moderne applikasjonsarkitektur.
Som alltid er koden tilgjengelig på GitHub.