<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-124  評論-49  文章-56  trackbacks-0

    什么是JNDI?為什么使用JNDI?

    JNDI是Java 命名與目錄接口(Java Naming and Directory Interface)

    要了解JNDI的作用,我們可以從“如果不用JNDI我們怎樣做?用了JNDI后我們又將怎樣做?”這個問題來探討。

    沒有JNDI的做法:
    程序員開發(fā)時,知道要開發(fā)訪問MySQL數(shù)據(jù)庫的應(yīng)用,于是將一個對 MySQL JDBC 驅(qū)動程序類的引用進行了編碼,并通過使用適當(dāng)?shù)?JDBC URL 連接到數(shù)據(jù)庫。
    就像以下代碼這樣:

    Connection conn=null;
    try {
       Class.forName("com.mysql.jdbc.Driver",true, Thread.currentThread().getContextClassLoader());        conn=DriverManager.getConnection("jdbc:mysql://MyDBServer?user=qingfeng&password=mingyue");  /* 使用conn并進行SQL操作 */     conn.close();
    } catch(Exception e) {
       e.printStackTrace();
    } finally {
       if(conn!=null) {
        try {       conn.close();   
        } catch(SQLException e) {
        }
    }}
    這是傳統(tǒng)的做法,這種做法一般在小規(guī)模的開發(fā)過程中不會產(chǎn)生問題,只要程序員熟悉Java語言、了解JDBC技術(shù)和MySQL,可以很快開發(fā)出相應(yīng)的應(yīng)用程序。

    沒有JNDI的做法存在的問題:
    1、數(shù)據(jù)庫服務(wù)器名稱MyDBServer 、用戶名和口令都可能需要改變,由此引發(fā)JDBC URL需要修改;
    2、數(shù)據(jù)庫可能改用別的產(chǎn)品,如改用DB2或者Oracle,引發(fā)JDBC驅(qū)動程序包和類名需要修改;
    3、隨著實際使用終端的增加,原配置的連接池參數(shù)可能需要調(diào)整;
    4、......

    解決辦法:
    程序員應(yīng)該不需要關(guān)心“具體的數(shù)據(jù)庫后臺是什么?JDBC驅(qū)動程序是什么?JDBC URL格式是什么?訪問數(shù)據(jù)庫的用戶名和口令是什么?”等等這些問題,程序員編寫的程序應(yīng)該沒有對 JDBC 驅(qū)動程序的引用,沒有服務(wù)器名稱,沒有用戶名稱或口令 —— 甚至沒有數(shù)據(jù)庫池或連接管理。而是把這些問題交給J2EE容器來配置和管理,程序員只需要對這些配置和管理進行引用即可。

    由此,就有了JNDI。

    用了JNDI之后的做法:
    首先,在在J2EE容器中配置JNDI參數(shù),定義一個數(shù)據(jù)源,也就是JDBC引用參數(shù),給這個數(shù)據(jù)源設(shè)置一個名稱;然后,在程序中,通過數(shù)據(jù)源名稱引用數(shù)據(jù)源從而訪問后臺數(shù)據(jù)庫。
    具體操作如下(以JBoss為例):
    1、配置數(shù)據(jù)源
    在JBoss的 D:\jboss420GA\docs\examples\jca 文件夾下面,有很多不同數(shù)據(jù)庫引用的數(shù)據(jù)源定義模板。將其中的 mysql-ds.xml 文件Copy到你使用的服務(wù)器下,如 D:\jboss420GA\server\default\deploy。
    修改 mysql-ds.xml 文件的內(nèi)容,使之能通過JDBC正確訪問你的MySQL數(shù)據(jù)庫,如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <datasources>
    <local-tx-datasource>
        <jndi-name>MySqlDS</jndi-name>
        <connection-url>jdbc:mysql://localhost:3306/lw</connection-url>
        <driver-class>com.mysql.jdbc.Driver</driver-class>
        <user-name>root</user-name>
        <password>rootpassword</password>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
        <metadata>
           <type-mapping>mySQL</type-mapping>
        </metadata>
    </local-tx-datasource>
    </datasources>

    這里,定義了一個名為MySqlDS的數(shù)據(jù)源,其參數(shù)包括JDBC的URL,驅(qū)動類名,用戶名及密碼等。

    2、在程序中引用數(shù)據(jù)源:

    Connection conn=null;
    try { 
    Context ctx=new InitialContext();
    Object datasourceRef=ctx.lookup("java:MySqlDS"); //引用數(shù)據(jù)源 
    DataSource ds=(Datasource)datasourceRef;  conn=ds.getConnection();  /* 使用conn進行數(shù)據(jù)庫SQL操作 */
    ...... 
    c.close();
    } catch(Exception e) { 
    e.printStackTrace();
    } finally {  if(conn!=null) {   
     try {    
     conn.close();   
     } catch(SQLException e) { }  }}
    直接使用JDBC或者通過JNDI引用數(shù)據(jù)源的編程代碼量相差無幾,但是現(xiàn)在的程序可以不用關(guān)心具體JDBC參數(shù)了。
    在系統(tǒng)部署后,如果數(shù)據(jù)庫的相關(guān)參數(shù)變更,只需要重新配置 mysql-ds.xml 修改其中的JDBC參數(shù),只要保證數(shù)據(jù)源的名稱不變,那么程序源代碼就無需修改。

    由此可見,JNDI避免了程序與數(shù)據(jù)庫之間的緊耦合,使應(yīng)用更加易于配置、易于部署。

    所以,在J2EE規(guī)范中,J2EE 中的資源并不局限于 JDBC 數(shù)據(jù)源。引用的類型有很多,其中包括資源引用(已經(jīng)討論過)、環(huán)境實體和 EJB 引用。特別是 EJB 引用,它暴露了 JNDI 在 J2EE 中的另外一項關(guān)鍵角色:查找其他應(yīng)用程序組件。

     

    JNDI原理

    sun只是提供了JNDI的接口(即規(guī)范),IBM, Novell, Sun 和 WebLogic 和JBOSS已經(jīng)為 JNDI 提供了服務(wù)提供程序,

    在JNDI中,在目錄結(jié)構(gòu)中的每一個結(jié)點稱為context。每一個JNDI名字都是相對于context的。這里沒有絕對名字的概念存在。對一個應(yīng)用來說,它可以通過使用 InitialContext 類來得到其第一個context: 

        Context ctx = new InitialContext();

        ctx.bind("name", Object);

        ctx.lookup("name");

    Context:上下文,我的理解是相當(dāng)與文件系統(tǒng)的中的目錄(JNDI的Naming Service是可以用操作系統(tǒng)的文件系統(tǒng)的,哈哈).

    entry/object:一個節(jié)點,相當(dāng)與文件系統(tǒng)中的目錄或文件.

    filter:查詢/過濾條件是一個字符串表達式如:(&(objectClass=top)(cn=*))查詢出objectClass屬性為top,cn屬性為所有情況的entry.

    Attribute:entry/object的屬性可以理解成JAVA對象的屬性,不同的是這個屬性可以多次賦值.

    A.將接口分為Context 和 DirContext  

       JNDI有兩個核心接口Context和DirContext,Context中包含 了基本的名字操作,而DirContext則將這些操作擴展到目錄服務(wù)。DirContext 對Context進行了擴展,提供了基本的目錄服務(wù)操作, 對名字對象屬性的維護、基于屬性的名字查找等等。  

    B.上下文列表的多種方法  

       一般來說有兩種進行上下文列表的應(yīng)用:上下文瀏覽應(yīng)用和對上下文中的對象進行實際操作的應(yīng)用。  

       上下文瀏覽應(yīng)用一般只需要顯示上下文中包含內(nèi)容的名字,或者再獲取一些諸如對象的類型之類的信息。這種類型的應(yīng)用一般都是交互式的,可以允許用戶在列舉的上下文列表中選擇一些進行進一步的顯示。  

       另外有一些應(yīng)用需要對上下文中的對象進行實際的操作,比如,一個備份程序需要對目錄中所有文件的狀態(tài)進行操作,或者某打印機管理員可能需要對大樓中的所有打印機進行復(fù)位。為了進行這樣的操作,程序需要獲取上下文中的實際對象。  

       對于這樣兩種類型的應(yīng)用,Context接口提供了兩種上下文列表方法list()和 listBindings()。其中l(wèi)ist()只返回一系列名字/類映射,而listBindings() 則返回名字、類和對象本身。顯然 list()用于上下文瀏覽應(yīng)用而listBindings()用于那些需要對對象進行實際操作的應(yīng)用。  
    例:
    =================將以下代碼段添加到server.xml中的<Host>中============
    <!-- configure DataSource. Add the following code into server.xml -->

    <Context path="/bookstore" docBase="bookstore" debug="0"
    reloadable="true" >

    <!-- 數(shù)據(jù)源名稱 -->
    <Resource name="jdbc/BookDB"
                   auth="Container"
                   type="javax.sql.DataSource" />

    <ResourceParams name="jdbc/BookDB">
        <parameter>
          <name>factory</name>
          <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
        </parameter>

        <!-- Maximum number of dB connections in pool. Make sure you
             configure your mysqld max_connections large enough to handle
             all of your db connections. Set to 0 for no limit.
             -->
    <!-- 活動狀態(tài)最大連接數(shù) -->
        <parameter>
          <name>maxActive</name>
          <value>100</value>
        </parameter>

        <!-- Maximum number of idle dB connections to retain in pool.
             Set to 0 for no limit.
             -->
    <!-- 空閑狀態(tài)數(shù)據(jù)庫連接最大數(shù) -->
        <parameter>
          <name>maxIdle</name>
          <value>30</value>
        </parameter>

        <!-- Maximum time to wait for a dB connection to become available
             in ms, in this example 10 seconds. An Exception is thrown if
             this timeout is exceeded. Set to -1 to wait indefinitely.
            Maximum time to wait for a dB connection to become available
             in ms, in this example 10 seconds. An Exception is thrown if
             this timeout is exceeded. Set to -1 to wait indefinitely.
             -->
    <!-- 數(shù)據(jù)庫處于空閑狀態(tài)的最長時間 -->
        <parameter>
          <name>maxWait</name>
          <value>10000</value>
        </parameter>

        <!-- MySQL dB username and password for dB connections -->
    <!-- 指定連接數(shù)據(jù)庫的用戶名及密碼 -->
        <parameter>
         <name>username</name>
         <value>dbuser</value>
        </parameter>
        <parameter>
         <name>password</name>
         <value>1234</value>
        </parameter>

        <!-- Class name for mm.mysql JDBC driver -->
    <!-- 指定JDBC驅(qū)動 -->
        <parameter>
           <name>driverClassName</name>
           <value>com.mysql.jdbc.Driver</value>
        </parameter>

        <!-- The JDBC connection url for connecting to your MySQL dB.
             The autoReconnect=true argument to the url makes sure that the
             mm.mysql JDBC Driver will automatically reconnect if mysqld closed the
             connection. mysqld by default closes idle connections after 8 hours.
             -->
    <!-- 指定連接數(shù)據(jù)庫的URL -->
        <parameter>
          <name>url</name>
          <value>jdbc:mysql://localhost:3306/BookDB?autoReconnect=true</value>
        </parameter>
    </ResourceParams>

    </Context> 
    運行機制:
    1、 首先程序代碼獲取初始化的 JNDI 環(huán)境并且調(diào)用 Context.lookup() 方法從 JNDI 服務(wù)提供者那里獲一個 DataSource 對象

    2、 中間層 JNDI 服務(wù)提供者返回一個 DataSource 對象給當(dāng)前的 Java 應(yīng)用程序這個 DataSource 對象代表了中間層服務(wù)上現(xiàn)存的緩沖數(shù)據(jù)源

    3、 應(yīng)用程序調(diào)用 DataSource 對象的 getConnection() 方法

    4、 當(dāng) DataSource 對象的 getConnection() 方法被調(diào)用時,中間層服務(wù)器將查詢數(shù)據(jù)庫 連接緩沖池中有沒有 PooledConnection 接口的實例對象。這個 PooledConnection 對象將被用于與數(shù)據(jù)庫建立物理上的數(shù)據(jù)庫連接

    5、 如果在緩沖池中命中了一個 PooledCoonection 對象那么連接緩沖池將簡單地更 新內(nèi)部的緩沖連接隊列并將該 PooledConnection 對象返回。如果在緩沖池內(nèi)沒 有找到現(xiàn)成的 PooledConnection 對象,那么 ConnectionPoolDataSource 接口將會被 用來產(chǎn)生一個新的 PooledConnection 對象并將它返回以便應(yīng)用程序使用

    6。 中間層服務(wù)器調(diào)用 PooledConnection 對象的 getConnection() 方法以便返還一個 java.sql.Connection 對象給當(dāng)前的 Java 應(yīng)用程序

    7、 當(dāng)中間層服務(wù)器調(diào)用 PooledConnection 對象的 getConnection() 方法時, JDBC 數(shù)據(jù) 庫驅(qū)動程序?qū)?chuàng)建一個 Connection 對象并且把它返回中間層服務(wù)器

    8、 中間層服務(wù)器將 Connection 對象返回給應(yīng)用程序 Java 應(yīng)用程序,可以認為這個 Connection 對象是一個普通的 JDBC Connection 對象使用它可以和數(shù)據(jù)庫建立。事 實上的連接與數(shù)據(jù)庫引擎產(chǎn)生交互操作 。

    9、 當(dāng)應(yīng)用程序不需要使用 Connection 對象時,可以調(diào)用 Connection 接口的 close() 方 法。請注意這種情況下 close() 方法并沒有關(guān)閉事實上的數(shù)據(jù)庫連接,僅僅是釋 放了被應(yīng)用程序占用的數(shù)據(jù)庫連接,并將它還給數(shù)據(jù)庫連接緩沖池,數(shù)據(jù)庫連接 緩沖池會自動將這個數(shù)據(jù)庫連接交給請求隊列中下一個的應(yīng)用程序使用。

    posted on 2010-02-23 10:36 junly 閱讀(1374) 評論(0)  編輯  收藏 所屬分類: jdbc/jndi

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 四虎成人精品在永久免费| 青青青国产在线观看免费网站| 国产一卡二卡≡卡四卡免费乱码 | 久久亚洲私人国产精品| 在线观看特色大片免费网站| 国产美女亚洲精品久久久综合| 久久av免费天堂小草播放| 亚洲一区二区三区在线视频| 你是我的城池营垒免费观看完整版| 中文字幕无码精品亚洲资源网| 国产精品内射视频免费| 亚洲精品色午夜无码专区日韩| 黄网站免费在线观看| 久久亚洲精品无码aⅴ大香| 国产成人精品免费视| 亚洲日韩一区精品射精| 日本不卡免费新一二三区| 猫咪www免费人成网站| 亚洲精品美女久久777777| 99re免费99re在线视频手机版| 亚洲成人免费网站| 色视频色露露永久免费观看| 黄色片网站在线免费观看| 久久亚洲精品中文字幕无码| 久久久久久曰本AV免费免费| 亚洲男同gay片| 亚洲国产成人a精品不卡在线| 最近中文字幕大全免费版在线| 亚洲精品影院久久久久久| 日本成人免费在线| 三年片在线观看免费| 亚洲an日韩专区在线| 亚洲精品成人区在线观看| 久久久久国产精品免费看| 亚洲av日韩综合一区二区三区| 国产亚洲精午夜久久久久久| 三年片在线观看免费大全| 免费观看又污又黄在线观看| 亚洲一区二区三区日本久久九| 四色在线精品免费观看| 久久国产精品国产自线拍免费|