<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的做法:
    程序員開發時,知道要開發訪問MySQL數據庫的應用,于是將一個對 MySQL JDBC 驅動程序類的引用進行了編碼,并通過使用適當的 JDBC URL 連接到數據庫。
    就像以下代碼這樣:

    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) {
        }
    }}
    這是傳統的做法,這種做法一般在小規模的開發過程中不會產生問題,只要程序員熟悉Java語言、了解JDBC技術和MySQL,可以很快開發出相應的應用程序。

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

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

    由此,就有了JNDI。

    用了JNDI之后的做法:
    首先,在在J2EE容器中配置JNDI參數,定義一個數據源,也就是JDBC引用參數,給這個數據源設置一個名稱;然后,在程序中,通過數據源名稱引用數據源從而訪問后臺數據庫。
    具體操作如下(以JBoss為例):
    1、配置數據源
    在JBoss的 D:\jboss420GA\docs\examples\jca 文件夾下面,有很多不同數據庫引用的數據源定義模板。將其中的 mysql-ds.xml 文件Copy到你使用的服務器下,如 D:\jboss420GA\server\default\deploy。
    修改 mysql-ds.xml 文件的內容,使之能通過JDBC正確訪問你的MySQL數據庫,如下:
    <?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的數據源,其參數包括JDBC的URL,驅動類名,用戶名及密碼等。

    2、在程序中引用數據源:

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

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

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

     

    JNDI原理

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

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

        Context ctx = new InitialContext();

        ctx.bind("name", Object);

        ctx.lookup("name");

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

    entry/object:一個節點,相當與文件系統中的目錄或文件.

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

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

    A.將接口分為Context 和 DirContext  

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

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

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

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

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

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

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

    <!-- 數據源名稱 -->
    <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.
             -->
    <!-- 活動狀態最大連接數 -->
        <parameter>
          <name>maxActive</name>
          <value>100</value>
        </parameter>

        <!-- Maximum number of idle dB connections to retain in pool.
             Set to 0 for no limit.
             -->
    <!-- 空閑狀態數據庫連接最大數 -->
        <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.
             -->
    <!-- 數據庫處于空閑狀態的最長時間 -->
        <parameter>
          <name>maxWait</name>
          <value>10000</value>
        </parameter>

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

        <!-- Class name for mm.mysql JDBC driver -->
    <!-- 指定JDBC驅動 -->
        <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.
             -->
    <!-- 指定連接數據庫的URL -->
        <parameter>
          <name>url</name>
          <value>jdbc:mysql://localhost:3306/BookDB?autoReconnect=true</value>
        </parameter>
    </ResourceParams>

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

    2、 中間層 JNDI 服務提供者返回一個 DataSource 對象給當前的 Java 應用程序這個 DataSource 對象代表了中間層服務上現存的緩沖數據源

    3、 應用程序調用 DataSource 對象的 getConnection() 方法

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

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

    6。 中間層服務器調用 PooledConnection 對象的 getConnection() 方法以便返還一個 java.sql.Connection 對象給當前的 Java 應用程序

    7、 當中間層服務器調用 PooledConnection 對象的 getConnection() 方法時, JDBC 數據 庫驅動程序將會創建一個 Connection 對象并且把它返回中間層服務器

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

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

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

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


    網站導航:
     
    主站蜘蛛池模板: 一级毛片成人免费看a| 亚洲国产精品精华液| 精品乱子伦一区二区三区高清免费播放 | 亚洲综合一区二区精品导航 | 亚洲精华液一二三产区| 免费看韩国黄a片在线观看| 91亚洲国产成人久久精品| 无码国产精品一区二区免费式直播| 亚洲精品免费在线观看| 午夜爽爽爽男女免费观看影院| 亚洲av丰满熟妇在线播放| 久久久久久夜精品精品免费啦| 亚洲五月六月丁香激情| 亚洲成年人免费网站| 亚洲综合av一区二区三区| 国产黄色片在线免费观看| 相泽南亚洲一区二区在线播放| 亚洲av午夜成人片精品电影| 一级做a爰片久久毛片免费看| 亚洲精品中文字幕乱码三区| 无码免费一区二区三区免费播放| 亚洲国产二区三区久久| 亚洲一区免费在线观看| 33333在线亚洲| vvvv99日韩精品亚洲| 免费无码作爱视频| 亚洲免费视频播放| 在线免费观看国产视频| 国产午夜无码精品免费看动漫| 亚洲精品视频在线播放| 国产精品久久免费视频| 中国国产高清免费av片| 亚洲国产精品久久人人爱| 日本一道本高清免费| 免费一级不卡毛片| 亚洲午夜一区二区三区| 中文字幕亚洲综合久久菠萝蜜| 亚洲精品视频免费在线观看| 亚洲日韩精品无码AV海量| 亚洲一区二区三区在线视频| 日韩插啊免费视频在线观看 |