Gambaran Umum Antaramuka Java dan Direktori

1. Pengenalan

Java Naming and Directory Interface (JNDI) menyediakan penggunaan perkhidmatan penamaan dan / atau direktori yang konsisten sebagai API Java. Antaramuka ini dapat digunakan untuk mengikat objek, mencari atau meminta objek, serta mengesan perubahan pada objek yang sama.

Walaupun penggunaan JNDI merangkumi senarai pelbagai perkhidmatan penamaan dan direktori yang disokong, dalam tutorial ini kita akan fokus pada JDBC sambil meneroka JNDI's API.

2. Penerangan JNDI

Sebarang kerja dengan JNDI memerlukan pemahaman mengenai perkhidmatan yang mendasari serta pelaksanaan yang dapat dicapai. Sebagai contoh, perkhidmatan sambungan pangkalan data memerlukan sifat tertentu dan pengendalian pengecualian.

Walau bagaimanapun, abstraksi JNDI memutuskan konfigurasi sambungan dari aplikasi.

Mari terokai Nama dan Konteks , yang mengandungi fungsi teras JNDI.

2.1. Antara Muka Nama

Name objectName = new CompositeName("java:comp/env/jdbc");

Antara muka Nama menyediakan keupayaan untuk mengurus nama komponen dan sintaks untuk nama JNDI. Token pertama rentetan mewakili konteks global, setelah itu setiap rentetan yang ditambahkan mewakili sub-konteks berikutnya:

Enumeration elements = objectName.getAll(); while(elements.hasMoreElements()) { System.out.println(elements.nextElement()); }

Keluaran kami kelihatan seperti:

java:comp env jdbc

Seperti yang kita dapat lihat, / adalah Pembatas untuk Nama sub-konteks. Sekarang, mari tambah subkonteks:

objectName.add("example");

Kemudian kami menguji penambahan kami:

assertEquals("example", objectName.get(objectName.size() - 1));

2.2. Antara Muka Konteks

Konteks mengandungi sifat untuk perkhidmatan penamaan dan direktori . Di sini, mari kita gunakan beberapa kod pembantu dari Spring untuk kemudahan membina Konteks :

SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); builder.activate();

SimpleNamingContextBuilder Spring membuat penyedia JNDI dan kemudian mengaktifkan pembangun dengan NamingManager :

JndiTemplate jndiTemplate = new JndiTemplate(); ctx = (InitialContext) jndiTemplate.getContext();

Akhirnya, JndiTemplate membantu kami mengakses InitialContext .

3. JNDI Objek Mengikat dan Mencari

Sekarang setelah kita melihat bagaimana menggunakan Nama dan Konteks , mari gunakan JNDI untuk menyimpan Sumber Data JDBC :

ds = new DriverManagerDataSource("jdbc:h2:mem:mydb");

3.1. Mengikat Objek JNDI

Oleh kerana kita mempunyai konteks, mari kita mengikat objek itu:

ctx.bind("java:comp/env/jdbc/datasource", ds);

Secara umum, perkhidmatan harus menyimpan rujukan objek, data bersiri, atau atribut dalam konteks direktori. Semuanya bergantung pada keperluan aplikasi.

Perhatikan bahawa menggunakan JNDI dengan cara ini kurang biasa. Biasanya, JNDI berinteraksi dengan data yang diuruskan di luar waktu operasi aplikasi.

Namun, jika aplikasi sudah dapat membuat atau menemukan DataSourcenya , mungkin lebih mudah untuk memasukkannya menggunakan Spring. Sebaliknya, jika sesuatu di luar aplikasi kita mengikat objek di JNDI, maka aplikasi tersebut dapat memakannya.

3.2. Mencari Objek JNDI

Mari cari Sumber Data kami :

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

Dan kemudian mari kita uji untuk memastikan bahawa DataSource seperti yang diharapkan:

assertNotNull(ds.getConnection());

4. Pengecualian JNDI yang biasa

Bekerja dengan JNDI kadang-kadang boleh menyebabkan pengecualian runtime. Berikut adalah beberapa perkara biasa.

4.1. NameNotFoundException

ctx.lookup("badJndiName");

Oleh kerana nama ini tidak terikat dalam konteks ini, kami melihat jejak timbunan ini:

javax.naming.NameNotFoundException: Name [badJndiName] not bound; 0 bindings: [] at org.springframework.mock.jndi.SimpleNamingContext.lookup(SimpleNamingContext.java:140) at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)

Kita harus perhatikan bahawa jejak tumpukan berisi semua objek yang terikat, yang berguna untuk mengesan mengapa pengecualian itu terjadi.

4.2. NoInitialContextException

Sebarang interaksi dengan InitialContext boleh membuang NoInitialContextException :

assertThrows(NoInitialContextException.class, () -> { JndiTemplate jndiTemplate = new JndiTemplate(); InitialContext ctx = (InitialContext) jndiTemplate.getContext(); ctx.lookup("java:comp/env/jdbc/datasource"); }).printStackTrace();

Kita harus perhatikan bahawa penggunaan JNDI ini sah, seperti yang kita gunakan sebelumnya. Namun, kali ini tidak ada penyedia konteks JNDI, dan pengecualian akan dilemparkan:

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or in an application resource file: java.naming.factory.initial at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:685)

5. Peranan JNDI dalam Senibina Aplikasi Moden

While JNDI plays less of a role in lightweight, containerized Java applications such as Spring Boot, there are other uses. Three Java technologies that still use JNDI are JDBC, EJB, and JMS. All have a wide array of uses across Java enterprise applications.

For example, a separate DevOps team may manage environment variables such as username and password for a sensitive database connection in all environments. A JNDI resource can be created in the web application container, with JNDI used as a layer of consistent abstraction that works in all environments.

This setup allows developers to create and control a local definition for development purposes while connecting to sensitive resources in a production environment through the same JNDI name.

6. Conclusion

Dalam tutorial ini, kami melihat menghubungkan, mengikat, dan mencari objek menggunakan Java Naming and Directory Interface. Kami juga melihat pengecualian umum yang dilemparkan oleh JNDI.

Akhirnya, kami melihat bagaimana JNDI sesuai dengan seni bina aplikasi moden.

Seperti biasa, kodnya tersedia di GitHub.