JNDI具體用法詳解
JNDI全稱(Java Naming and Directory Interface),是java命名和目錄接口。它是一個應用程序設(shè)計的API,為開發(fā)人員提供了查找和訪問各種命名和目錄服務(wù)的通用、統(tǒng)一的接口,類似JDBC都是構(gòu)建在抽象層上。
1、命名的概念與應用
JNDI中的命名(Naming),就是將Java對象以某個名稱的形式綁定(binding)到一個容器環(huán)境(Context)中,以后調(diào)用容器環(huán)境到JNDI容器環(huán)境(Context)的查找(lookup)方法又可以查找出某個名稱所綁定的Java對象。
這樣做的好處在于在真實的項目應用中,通常是由系統(tǒng)程序或框架程序先將資源對象綁定到JNDI環(huán)境中,以后在該系統(tǒng)或框架中運行的模塊程序就可以從JNDI環(huán)境中查找這些資源對象了。比如,Tomcat服務(wù)器在啟動時可以創(chuàng)建一個連接到某種數(shù)據(jù)庫系統(tǒng)的數(shù)據(jù)源(DataSource)對象,并將該數(shù)據(jù)源(DataSource)對象綁定到JNDI環(huán)境中,以后在這個Tomcat服務(wù)器中運行的Servlet和JSP程序就可以從JNDI環(huán)境中查詢出這個數(shù)據(jù)源(DataSource)對象進行使用,而不用關(guān)心數(shù)據(jù)源(DataSource)對象是如何創(chuàng)建出來的,這種方式極大的增強了系統(tǒng)的可維護性,這樣,當數(shù)據(jù)庫系統(tǒng)的連接參數(shù)發(fā)生變更時,就只是Tomcat系統(tǒng)管理員一個人要關(guān)心的事情,而與所有的應用程序開發(fā)人員無關(guān)。
容器環(huán)境(Context)本身也是一個Java對象,它可以通過一個名稱綁定到另一個容器環(huán)境中。將一個Context對象綁定到另一個Context對象中,這就形成了一種父子級聯(lián)關(guān)系,多個Context對象最終可以級聯(lián)成一種樹狀結(jié)構(gòu),樹中的每個Context對象中都可以綁定若干個Java對象。
上圖中的每個方框分別代表以后個Context對象,它們分別綁定的名稱分別為a、b、c、d、e,其中b和c是a的子Context,d是b的子Context,e又是d的子Context。各個方框內(nèi)的每個小橢圓分別代表一個Java對象,它們也都有一個綁定的名稱,這些名稱分別為dog、pig、sheet等,在同一個Context不能綁定兩個相同名稱的Java對象,在不同的Context中可以出現(xiàn)同名的綁定對象??梢?,Context樹的級聯(lián)結(jié)構(gòu)與文件系統(tǒng)中的目錄結(jié)構(gòu)非常類似,Context與其中綁定的Java對象的關(guān)系也非常類似于文件系統(tǒng)的目錄與文件的關(guān)系。
想要得到一個Context對象,就可以調(diào)用它的查詢(lookup)方法來獲得其中綁定的java對象。另外,調(diào)用某個Context對象的lookup方法也可以獲得Context樹中的任意一個Context對象,這只需要在lookup方法中指定相應的Context路徑即可。
在JNDI中不存在著“根”Context的概念,也就是說,執(zhí)行JNDI操作不是從一個“根”Context對象開始,而是可以從Context樹中的任意以后個Context開始。如論如何程序必須獲得一個作為操作入口的Context對象后才能執(zhí)行各種JNDI命名操作,為此,JNDI API中提供了一個InitialContext類來創(chuàng)建用作JNDI命名操作的入口Context對象。
Context是一個接口,Context對象實際上是Context的某個實現(xiàn)類的實例對象,選擇這個具體的Context實現(xiàn)類并創(chuàng)建其實例對象的過程是由一個Context工廠類來完成的,這個工廠類的類名可以通過JNDI的環(huán)境屬性java.naming.factory.initial指定,也可以根據(jù)Context的操作方法的url參數(shù)的Schema來選擇。
2、目錄的概念與應用
JNDI中的目錄(Directory)與文件系統(tǒng)中的目錄概念有很大的不同,JNDI中的目錄(Directory)是指將一個對象的所有屬性信息保存到一個容器環(huán)境中。JNDI的目錄(Directory)原理與JNDI的命令(Naming)原理非常相似,主要的區(qū)別在于目錄容器環(huán)境中保存的是對象的屬性信息,而不是對象本身,所以,目錄提供的是對屬性的各種操作。事實上,JNDI的目錄(Directory)與命名(Naming)往往是結(jié)合在一起使用的,JNDI API中提供的代表目錄容器環(huán)境的類為DirContext,DirContext是Context的子類,顯然它除了能完成目錄相關(guān)操作外,也能完成所有的命令(Naming)操作。DirContext是對Context的擴展,它在Context的基礎(chǔ)上增加了對目錄屬性的操作功能,可以在其中綁定對象的屬性信息和查找對象的屬性信息。JNDI中的目錄(Directory)的結(jié)構(gòu)示意圖如下:
上圖中的每個外層的方框分別代表一個DirContext對象,它們綁定的名稱分別為a、b,b是a的子DirContext。圖中的每個小橢圓分別代表一個java對象,各個里層的方框分別代表一個對象屬性。從名稱為a的DirContext中的內(nèi)容可以看到,一個DirContext容器環(huán)境中即可以綁定對象自身,也可以綁定對象的屬性信息,綁定的對象和綁定的屬性是完全獨立的兩個事物,即使它們的綁定名稱相同,它們的操作也是完全獨立的。另外,一個屬性可以有多個屬性值,例如,dog對象的category屬性就設(shè)置了兩個屬性值:meat和pet。
從名稱為b的DirContext中的內(nèi)容可以看到,一個DirContext容器環(huán)境中也可以只綁定對象的屬性信息,而不綁定任何對象自身。與Context的操作原理類似,JNDI API中提供了一個InitialDirContext類創(chuàng)建用作JNDI命名與目錄屬性操作的入口DirContext對象。
3、JNDI的用法:創(chuàng)建一個數(shù)據(jù)源
沒有JNDI時的做法
Connection conn = null; try{ Class.forName("com.mysql.jdbc.Driver",true,Thread.currentThread().getContextClassLoader()); conn = DriverManager.getConnection("jdbc:mysql://MyDBServer?user=xxx&password=xxx"); ..... conn.close(); }catch(Exception e){ e.printStackTrace(); }finally{ if(conn!=null){ try{ conn.close(); }catch(SQLException e){} } }
這種做法只適用于小規(guī)模開發(fā),在大規(guī)模開發(fā)中就會存在許多問題,比如:
- 數(shù)據(jù)庫服務(wù)器名稱MyDBServer、用戶名和口令都可能需要改變,由此引發(fā)JDBC URL需要修改。
- 數(shù)據(jù)庫可能改用別的產(chǎn)品,引發(fā)JDBC驅(qū)動程序包和類名需要修改。
- 隨著實際使用終端的增加,原配置的連接池參數(shù)可能需要調(diào)整。
在開發(fā)過程中,程序員應該不需要關(guān)心“具體的數(shù)據(jù)庫后臺是什么?JDBC驅(qū)動程序是什么?”等這些問題,程序員編寫的程序應該沒有對JDBC驅(qū)動程序的引用,沒有服務(wù)器名稱,沒有用戶名稱等,而是把這些問題交給容器來配置和管理,這樣程序員只需要對這些配置和管理進行引用即可。
使用JNDI
context.xml配置數(shù)據(jù)庫連接信息:
<?xml version="1.0" encoding="UTF-8"?> <Context> <!-- Default set of monitored resources. If one of these changes, the --> <!-- web application will be reloaded. --> <WatchedResource>WEB-INF/web.xml</WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> <!-- Uncomment this to disable session persistence across Tomcat restarts --> <!--<Manager pathname="" />--> <Resource name="jdbc/mysql" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/task" username="root" password="123456" maxTotal="20" maxIdle="10" maxWaitMillis="-1"/> </Context>
web.xml中引入數(shù)據(jù)源:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <resource-ref> <res-ref-name>jdbc/mysql</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app>
獲取Connection對象,查詢數(shù)據(jù)庫:
import javax.naming.Context; import javax.naming.InitialContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @WebServlet("/test") public class Servlet1 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException { try { Context initContext = new InitialContext(); Context envContext = (Context) initContext.lookup("java:/comp/env"); DataSource ds = (DataSource) envContext.lookup("jdbc/mysql"); Connection conn = ds.getConnection(); PreparedStatement ps = conn.prepareStatement("select * from t_role"); ResultSet rs = ps.executeQuery(); System.out.println(rs.next()); rs.close(); conn.close(); } catch (Exception e) { e.printStackTrace(); } } }
到此這篇關(guān)于JNDI具體用法詳解的文章就介紹到這了,更多相關(guān)JNDI 用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot整合Shiro實現(xiàn)登錄認證的方法
這篇文章主要介紹了SpringBoot整合Shiro實現(xiàn)登錄認證的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02MyBatis Plus插件機制與執(zhí)行流程原理分析詳解
這篇文章主要介紹了MyBatis Plus插件機制與執(zhí)行流程原理分析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09使用jenkins+maven+git發(fā)布jar包過程詳解
這篇文章主要介紹了使用jenkins+maven+git發(fā)布jar包過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-07-07