JavaRush /Blog Jawa /Random-JV /Nggunakake JNDI ing Jawa
Анзор Кармов
tingkat
Санкт-Петербург

Nggunakake JNDI ing Jawa

Diterbitake ing grup
Hello! Dina iki kita bakal ngenalake sampeyan JNDI. Ayo goleki apa iku, kenapa perlu, cara kerjane, kepiye carane bisa. Banjur kita bakal nulis tes unit Spring Boot, ing njero kita bakal main karo JNDI iki. Nggunakake JNDI ing Jawa - 1

Pambuka. Layanan Jeneng lan Direktori

Sadurunge nyilem menyang JNDI, ayo padha ngerti apa layanan jeneng lan direktori. Conto paling jelas saka layanan kasebut yaiku sistem file ing PC, laptop utawa smartphone. Sistem file ngatur file (cukup aneh). File ing sistem kasebut dikelompokake ing struktur wit. Saben berkas nduweni jeneng lengkap sing unik, contone: C:\windows\notepad.exe. Wigati dicathet: jeneng berkas lengkap minangka path saka sawetara titik root (drive C) menyang file kasebut (notepad.exe). Node penengah ing rantai kasebut yaiku direktori (direktori windows). File ing direktori duwe atribut. Contone, "Didhelikake", "Mung-Waca", lan liya-liyane. Katrangan rinci babagan prasaja kaya sistem file bakal mbantu luwih ngerti definisi jeneng lan layanan direktori. Dadi, layanan jeneng lan direktori minangka sistem sing ngatur pemetaan akeh jeneng menyang akeh obyek. Ing sistem file kita, kita sesambungan karo jeneng file sing ndhelikake obyek-file dhewe ing macem-macem format. Ing layanan jeneng lan direktori, obyek sing dijenengi diatur dadi struktur wit. Lan obyek direktori duwe atribut. Conto liyane saka layanan jeneng lan direktori yaiku DNS (Domain Name System). Sistem iki ngatur pemetaan antarane jeneng domain sing bisa diwaca manungsa (contone, https://javarush.com/) lan alamat IP sing bisa diwaca mesin (contone, 18.196.51.113). Saliyane DNS lan sistem file, ana akeh layanan liyane, kayata:

JNDI

JNDI, utawa Java Naming and Directory Interface, minangka API Java kanggo ngakses layanan jeneng lan direktori. JNDI minangka API sing nyedhiyakake mekanisme seragam kanggo program Java kanggo sesambungan karo macem-macem layanan jeneng lan direktori. Ing hood, integrasi antarane JNDI lan layanan tartamtu wis rampung nggunakake Service Provider Interface (SPI). SPI ngidini macem-macem layanan jeneng lan direktori disambungake kanthi transparan, ngidini aplikasi Java nggunakake API JNDI kanggo ngakses layanan sing disambungake. Gambar ing ngisor iki nggambarake arsitektur JNDI: Nggunakake JNDI ing Jawa - 2

Sumber: Oracle Java Tutorials

JNDI. Tegese ing tembung prasaja

Pitakonan utama yaiku: kenapa kita butuh JNDI? JNDI dibutuhake supaya kita bisa njaluk obyek Jawa saka sawetara "Registration" obyek saka kode Jawa kanthi jeneng obyek kaiket kanggo obyek iki. Pratelan ing ndhuwur dipecah dadi tesis supaya akeh tembung sing bola-bali ora mbingungake:
  1. Wekasanipun kita kudu njaluk obyek Jawa.
  2. Kita bakal entuk obyek iki saka sawetara pendaptaran.
  3. Ana akeh obyek ing registri iki.
  4. Saben obyek ing registri iki nduweni jeneng unik.
  5. Kanggo entuk obyek saka registri, kita kudu menehi jeneng ing panyuwunan kita. Kaya-kaya ngomong: "Mangga paringana apa sing sampeyan duwe jeneng iki lan iki."
  6. Kita ora mung bisa maca obyek kanthi jeneng saka registri, nanging uga nyimpen obyek ing registri iki ing jeneng tartamtu (piye wae, padha mungkasi munggah ana).
Dadi, kita duwe sawetara jinis pendaptaran, utawa panyimpenan obyek, utawa JNDI Tree. Salajengipun, kanthi ngginakaken tuladha, sumangga kita mangertosi tegesipun JNDI. Wigati dicathet yen umume JNDI digunakake ing pangembangan Enterprise. Lan aplikasi kasebut bisa digunakake ing sawetara server aplikasi. Server iki bisa uga sawetara Server Aplikasi Java EE, utawa wadhah servlet kaya Tomcat, utawa wadhah liyane. Registri obyek dhewe, yaiku, JNDI Tree, biasane ana ing server aplikasi iki. Sing terakhir ora mesthi dibutuhake (sampeyan bisa duwe wit kasebut sacara lokal), nanging paling khas. JNDI Tree bisa dikelola dening wong khusus (administrator sistem utawa spesialis DevOps) sing bakal "nyimpen ing registri" obyek kanthi jenenge. Nalika aplikasi kita lan JNDI Tree dumunung bebarengan ing wadhah sing padha, kita bisa kanthi gampang ngakses sembarang obyek Jawa sing disimpen ing pendaptaran kuwi. Kajaba iku, registri lan aplikasi kita bisa ditemokake ing wadhah sing beda-beda lan uga ing mesin fisik sing beda. JNDI malah ngidini sampeyan ngakses obyek Jawa saka adoh. Kasus khas. Administrator server Java EE nyelehake obyek ing pendaptaran sing nyimpen informasi sing dibutuhake kanggo nyambungake menyang database. Mulane, kanggo nggarap database, kita mung bakal njaluk obyek sing dibutuhake saka wit JNDI lan nggarap. Iku banget nyaman. Penak uga ana ing kasunyatan manawa ing pangembangan perusahaan ana macem-macem lingkungan. Ana server produksi, lan ana server test (lan asring ana luwih saka 1 server test). Banjur, kanthi nempatake obyek kanggo nyambungake menyang database ing saben server ing JNDI lan nggunakake obyek iki ing aplikasi kita, kita ora kudu ngganti apa-apa nalika masang aplikasi saka siji server (test, release) menyang liyane. Bakal ana akses menyang database ing endi wae. Contone, mesthine rada disederhanakake, nanging muga-muga bisa mbantu sampeyan luwih ngerti kenapa JNDI dibutuhake. Sabanjure, kita bakal luwih ngerti JNDI ing Jawa, kanthi sawetara unsur serangan.

JNDI API

JNDI kasedhiya ing platform Java SE. Kanggo nggunakake JNDI, sampeyan kudu ngimpor kelas JNDI, uga siji utawa luwih panyedhiya layanan kanggo ngakses layanan jeneng lan direktori. JDK kalebu panyedhiya layanan kanggo layanan ing ngisor iki:
  • Protokol Akses Direktori Ringan (LDAP);
  • Arsitektur Broker Panjaluk Objek Umum (CORBA);
  • Layanan jeneng Layanan Objek Umum (COS);
  • Registry Java Remote Method Invocation (RMI);
  • Layanan Jeneng Domain (DNS).
Kode API JNDI dipérang dadi sawetara paket:
  • javax.naming;
  • javax.naming.directory;
  • javax.naming.ldap;
  • javax.naming.event;
  • javax.naming.spi.
Kita bakal miwiti introduksi JNDI kanthi rong antarmuka - Jeneng lan Konteks, sing ngemot fungsi utama JNDI

Jeneng Antarmuka

Antarmuka Jeneng ngidini sampeyan ngontrol jeneng komponen uga sintaks jeneng JNDI. Ing JNDI, kabeh operasi jeneng lan direktori dileksanakake relatif marang konteks. Ora ana oyod sing mutlak. Mulane, JNDI nemtokake InitialContext, sing nyedhiyakake titik wiwitan kanggo operasi jeneng lan direktori. Sawise konteks wiwitan diakses, bisa digunakake kanggo nggoleki obyek lan konteks liyane.
Name objectName = new CompositeName("java:comp/env/jdbc");
Ing kode ing ndhuwur, kita nemtokake sawetara jeneng ing ngendi sawetara obyek dumunung (bisa uga ora ana, nanging kita ngetang). Tujuan pungkasan kita yaiku njupuk referensi kanggo obyek iki lan digunakake ing program kita. Dadi, jeneng kasebut kalebu sawetara bagean (utawa token), dipisahake kanthi garis miring. Token kasebut diarani konteks. Sing pisanan mung konteks, kabeh sing sabanjure minangka sub-konteks (sabanjuré diarani subkonteks). Konteks luwih gampang dingerteni yen sampeyan nganggep padha karo direktori utawa direktori, utawa mung folder biasa. Konteks root yaiku folder root. Subkonteks minangka subfolder. Kita bisa ndeleng kabeh komponen (konteks lan subkonteks) saka jeneng tartamtu kanthi mbukak kode ing ngisor iki:
Enumeration<String> elements = objectName.getAll();
while(elements.hasMoreElements()) {
  System.out.println(elements.nextElement());
}
Output bakal kaya ing ngisor iki:

java:comp
env
jdbc
Output nuduhake yen token ing jeneng dipisahake saka saben liyane kanthi garis miring (Nanging, kita kasebut iki). Saben token jeneng duwe indeks dhewe. Indeksing token diwiwiti ing 0. Konteks root duwe indeks nol, konteks sabanjure duwe indeks 1, sabanjure 2, etc. Kita bisa entuk jeneng subkonteks kanthi indeks:
System.out.println(objectName.get(1)); // -> env
Kita uga bisa nambah token tambahan (ing pungkasan utawa ing lokasi tartamtu ing indeks):
objectName.add("sub-context"); // Добавит sub-context в конец
objectName.add(0, "context"); // Добавит context в налачо
Dhaptar cara lengkap bisa ditemokake ing dokumentasi resmi .

Konteks Antarmuka

Antarmuka iki ngemot seperangkat konstanta kanggo miwiti konteks, uga sakumpulan cara kanggo nggawe lan mbusak konteks, ngiket obyek menyang jeneng, lan nggoleki lan njupuk obyek. Ayo goleki sawetara operasi sing ditindakake nggunakake antarmuka iki. Tindakan sing paling umum yaiku nggoleki obyek kanthi jeneng. Iki ditindakake kanthi nggunakake metode:
  • Object lookup(String name)
  • Object lookup(Name name)
Naleni obyek menyang jeneng ditindakake kanthi nggunakake metode bind:
  • void bind(Name name, Object obj)
  • void bind(String name, Object obj)
Kaloro cara kasebut bakal ngiket jeneng jeneng menyang obyek. Object Operasi invers saka naleni - unbinding obyek saka jeneng, ditindakake kanthi nggunakake metode unbind:
  • void unbind(Name name)
  • void unbind(String name)
Dhaptar lengkap cara kasedhiya ing situs web dokumentasi resmi .

Konteks Awal

InitialContextiku kelas sing makili unsur ROOT saka wit JNDI lan ngleksanakake ing Context. Sampeyan kudu nggoleki obyek kanthi jeneng ing wit JNDI relatif marang simpul tartamtu. Simpul oyod wit bisa dadi simpul kasebut InitialContext. Kasus panggunaan khas kanggo JNDI yaiku:
  • njaluk InitialContext.
  • Gunakake InitialContextkanggo njupuk obyek kanthi jeneng saka wit JNDI.
Ana sawetara cara kanggo njaluk InitialContext. Iku kabeh gumantung ing lingkungan ing ngendi program Jawa dumunung. Contone, yen program Java lan wit JNDI mlaku ing server aplikasi sing padha, cukup InitialContextgampang kanggo njaluk:
InitialContext context = new InitialContext();
Yen ora, njupuk konteks dadi luwih angel. Kadhangkala perlu kanggo ngliwati dhaptar properti lingkungan kanggo miwiti konteks:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.fscontext.RefFSContextFactory");

Context ctx = new InitialContext(env);
Conto ing ndhuwur nuduhake salah sawijining cara kanggo miwiti konteks lan ora nggawa beban semantik liyane. Ora perlu nyilem menyang kode kanthi rinci.

Conto nggunakake JNDI ing tes unit SpringBoot

Ing nginggil, kadhawuhaken bilih JNDI saged sesrawungan kaliyan layanan nama lan direktori, perlu wonten SPI (Service Provider Interface), kanthi bantuan integrasi antawisipun Jawi kaliyan jasa penamaan. JDK standar dilengkapi karo sawetara SPI sing beda-beda (kita kadhaptar ing ndhuwur), sing saben-saben ora kapentingan kanggo tujuan demonstrasi. Ngunggahake aplikasi JNDI lan Java ing njero wadhah rada menarik. Nanging, penulis artikel iki minangka wong kesed, supaya kanggo nduduhake cara kerjane JNDI, dheweke milih dalan sing paling ora tahan: mbukak JNDI ing tes unit aplikasi SpringBoot lan ngakses konteks JNDI nggunakake hack cilik saka Spring Framework. Dadi, rencana kita:
  • Ayo nulis proyek Spring Boot kosong.
  • Ayo nggawe tes unit ing proyek iki.
  • Ing tes, kita bakal nduduhake nggarap JNDI:
    • entuk akses menyang konteks;
    • ikatan (ikatan) sawetara obyek ing sawetara jeneng ing JNDI;
    • njaluk barang kanthi jeneng (lookup);
    • Ayo priksa manawa obyek kasebut ora null.
Ayo dadi miwiti ing urutan. File->New->Project... Nggunakake JNDI ing Jawa - 3 Sabanjure, pilih item Spring Initializr : Nggunakake JNDI ing Jawa - 4Isi metadata babagan proyek: Nggunakake JNDI ing Jawa - 5Banjur pilih komponen Spring Framework sing dibutuhake. Kita bakal ngiket sawetara obyek DataSource, mula kita butuh komponen kanggo nggarap database:
  • JDBC API;
  • H2 Ddatabase.
Nggunakake JNDI ing Jawa - 6Ayo nemtokake lokasi ing sistem file: Nggunakake JNDI ing Jawa - 7Lan proyek digawe. Nyatane, siji tes unit digawe kanthi otomatis kanggo kita, sing bakal digunakake kanggo tujuan demonstrasi. Ing ngisor iki struktur proyek lan tes sing dibutuhake: Nggunakake JNDI ing Jawa - 8Ayo miwiti nulis kode ing tes contextLoads. A hack cilik saka Spring, rembugan ndhuwur, punika kelas SimpleNamingContextBuilder. Kelas iki dirancang kanggo gampang ngunggahake JNDI ing tes unit utawa aplikasi mandiri. Ayo nulis kode kanggo entuk konteks:
final SimpleNamingContextBuilder simpleNamingContextBuilder
       = new SimpleNamingContextBuilder();
simpleNamingContextBuilder.activate();

final InitialContext context = new InitialContext();
Rong baris kode pisanan bakal ngidini kita miwiti konteks JNDI kanthi gampang mengko. Tanpa wong-wong mau, InitialContextpangecualian bakal dibuwang nalika nggawe conto javax.naming.NoInitialContextException:. Penafian. Kelas kasebut SimpleNamingContextBuilderminangka kelas Deprecated. Lan conto iki dimaksudake kanggo nuduhake carane sampeyan bisa nggarap JNDI. Iki dudu praktik paling apik kanggo nggunakake tes unit JNDI. Iki bisa diarani minangka crutch kanggo mbangun konteks lan nduduhake naleni lan njupuk obyek saka JNDI. Sawise nampa konteks, kita bisa ngekstrak obyek kasebut utawa nggoleki obyek ing konteks kasebut. Ora ana obyek ing JNDI, mula logis yen dilebokake ing kana. Tuladhane, DriverManagerDataSource:
context.bind("java:comp/env/jdbc/datasource", new DriverManagerDataSource("jdbc:h2:mem:mydb"));
Ing baris iki, kita wis bound obyek kelas DriverManagerDataSourcekanggo jeneng java:comp/env/jdbc/datasource. Sabanjure, kita bisa njaluk obyek saka konteks kanthi jeneng. Kita ora duwe pilihan kajaba kanggo njaluk obyek sing mung kita sijine, amarga ora ana obyek liyane ing konteks =(
final DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/datasource");
Saiki ayo priksa manawa DataSource kita duwe sambungan (sambungan, sambungan utawa sambungan minangka kelas Java sing dirancang kanggo nggarap database):
assert ds.getConnection() != null;
System.out.println(ds.getConnection());
Yen kita nindakake kabeh kanthi bener, output bakal kaya iki:

conn1: url=jdbc:h2:mem:mydb user=
Iku worth ngomong sing sawetara baris kode bisa uncalan pangecualian. Garis ing ngisor iki dibuwang javax.naming.NamingException:
  • simpleNamingContextBuilder.activate()
  • new InitialContext()
  • context.bind(...)
  • context.lookup(...)
Lan nalika nggarap kelas DataSourcebisa dibuwang java.sql.SQLException. Ing babagan iki, perlu kanggo nglakokake kode ing njero blok try-catch, utawa nuduhake ing tandha unit tes sing bisa mbuwang pengecualian. Punika kode lengkap kelas tes:
@SpringBootTest
class JndiExampleApplicationTests {

    @Test
    void contextLoads() {
        try {
            final SimpleNamingContextBuilder simpleNamingContextBuilder
                    = new SimpleNamingContextBuilder();
            simpleNamingContextBuilder.activate();

            final InitialContext context = new InitialContext();

            context.bind("java:comp/env/jdbc/datasource", new DriverManagerDataSource("jdbc:h2:mem:mydb"));

            final DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/datasource");

            assert ds.getConnection() != null;
            System.out.println(ds.getConnection());

        } catch (SQLException | NamingException e) {
            e.printStackTrace();
        }
    }
}
Sawise mbukak tes, sampeyan bisa ndeleng log ing ngisor iki:

o.s.m.jndi.SimpleNamingContextBuilder    : Activating simple JNDI environment
o.s.mock.jndi.SimpleNamingContext        : Static JNDI binding: [java:comp/env/jdbc/datasource] = [org.springframework.jdbc.datasource.DriverManagerDataSource@4925f4f5]
conn1: url=jdbc:h2:mem:mydb user=

Kesimpulan

Dina iki kita nyawang JNDI. Kita sinau babagan layanan jeneng lan direktori, lan JNDI minangka API Java sing ngidini sampeyan sesambungan kanthi seragam karo layanan sing beda saka program Java. Yaiku, kanthi bantuan JNDI, kita bisa ngrekam obyek ing wit JNDI kanthi jeneng tartamtu lan nampa obyek sing padha kanthi jeneng. Minangka tugas bonus, sampeyan bisa mbukak conto carane JNDI dianggo. Ikatan sawetara obyek liyane menyang konteks, banjur waca obyek iki kanthi jeneng.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION