JNDI 是什麼

JNDI是 Java 命名與目錄接口(Java Naming and Directory Interface),在J2EE規範中是重要的規範之一,不少專家認爲,沒有透徹理解JNDI的意義和作用,就沒有真正掌握J2EE特別是EJB的知識。
那麼,JNDI到底起什麼作用?

要了解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程序員(如Delphi、VB等)常見的做法。這種做法一般在小規模的開發過程中不會產生問題,只要程序員熟悉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避免了程序與數據庫之間的緊耦合,使應用更加易於配置、易於部署。

JNDI的擴展:
JNDI在滿足了數據源配置的要求的基礎上,還進一步擴充了作用:所有與系統外部的資源的引用,都可以通過JNDI定義和引用。

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

EJB 的 JNDI 引用非常類似於 JDBC 資源的引用。在服務趨於轉換的環境中,這是一種很有效的方法。可以對應用程序架構中所得到的所有組件進行這類配置管理,從 EJB 組件到 JMS 隊列和主題,再到簡單配置字符串或其他對象,這可以降低隨時間的推移服務變更所產生的維護成本,同時還可以簡化部署,減少集成工作。 外部資源”。 


總結:
J2EE 規範要求所有 J2EE 容器都要提供 JNDI 規範的實現。JNDI 在 J2EE 中的角色就是“交換機” —— J2EE 組件在運行時間接地查找其他組件、資源或服務的通用機制。在多數情況下,提供 JNDI 供應者的容器可以充當有限的數據存儲,這樣管理員就可以設置應用程序的執行屬性,並讓其他應用程序引用這些屬性(Java 管理擴展(Java Management Extensions,JMX)也可以用作這個目的)。JNDI 在 J2EE 應用程序中的主要角色就是提供間接層,這樣組件就可以發現所需要的資源,而不用瞭解這些間接性。

在 J2EE 中,JNDI 是把 J2EE 應用程序合在一起的粘合劑,JNDI 提供的間接尋址允許跨企業交付可伸縮的、功能強大且很靈活的應用程序。這是 J2EE 的承諾,而且經過一些計劃和預先考慮,這個承諾是完全可以實現的





JNDI 筆記(一) 概述

NDI,Java Naming Directory Interface,J2EE的標準之一,所有的J2EE容器都必須提供一個JNDI的服務,但是,我一直都沒用過,至少是沒有刻意地去用過。因爲,我也 曾經把數據源配置在Tomcat的JNDI服務中,但那時,我也只是剛剛涉足JAVA,有人告訴我應該這麼幹而已。後來,我開始使用自定義的數據庫連接配 置文件,就再也沒有跟JNDI打過交道了,直到今天。

現在之所以又想看一下,只是因爲覺得這是J2EE的重要標準之一,如果不懂得的話,似乎有點說不過去。

JNDI 的主要功能可以這樣描述,它使用一張哈希表存儲對象(大多數的J2EE容器也的確是這樣做的),然後,開發人員可以使用鍵值——也就是一個字符串——來獲 取這個對象。這裏就包括取JNDI的兩個最主要操作,bind和lookup。bind操作負責往哈希表裏存對象,存對象的時候要定義好對象的鍵值字符 串,lookup則根據這個鍵值字符串往外取對象。

JNDI的命稱可能會讓人產生混淆,似乎覺得這是一個用來操作目錄的,事實上,我更願意把這個目錄理解成爲JNDI存放對象時使用的格式,也就是說,JNDI以目錄的方式存儲對象的屬性。例如,用戶通過JNDI存儲一個汽車對象,那麼,汽 車就是根目錄,汽車的輪子、引擎之類的子對象就算是子目錄,而屬性,比如說汽車的牌子、重量之類,就算是汽車目錄下的文件。

JNDI的功能既然就是根據一個字符串鍵值就可以取得一個想要得到的對象,我一開始就覺得這不是跟COM或CORBA一樣嗎?SUN也是有野心的企業啊,JNDI應該就是它要努力推行的JAVA下的分佈式開發的標準吧。

JNDI 的出現應該就是爲了分步式開發服務的,有人負責開發這種分佈式對象,有人只需要使用這些分佈式對象就可以了,這兩組人不必屬於同一個公司,而且這種開發通 常應該是不併行的,也不必是會了同一個項目服務。就如果數據源對象,它放在JNDI中,只要想要用的人,直接通過JNDI服務取來用就可以了,至於當初是 誰把它放進JNDI中的,還是不用操這份心了吧。而我一直沒有使用JNDI,也就是這個原因,項目中的所有對象都在我控制之下,我不去使用別人的對象,也 沒打算把我的對象貢獻出來給別人使用,那自然也就沒必要去跟JNDI打交道。我覺得是否使用JNDI,這應該是關鍵原因,至於什麼方便性、安全性之類的考 慮,應該不是JNDI的主要目的,就如同你可以用JAVA來做網站,但JAVA並不是專門用來做網站的。

可能有人覺得這種功能跟IoC也 很象,這個我倒不覺得,雖然對於對象的使用人員來說的確是這種感覺,且不說IoC需要爲對象定義接口,而JNDI並無此限制,先說這裏有一個使用環境問 題,我覺得IoC是用來解決並行開發問題的,也就是說IoC主要是用於明確設計人員與實現/使用人員的分工,無論是設計的,還是使用的,通常是一個項目組 裏的人,使用IoC,可以使得設計人員專注於設計,加快設計速度。因此,IoC的用途要比JNDI廣泛的多,現在大型系統中,不使用IoC的,幾稀矣。

JNDI 筆記(二) J2EE下使用JNDI

在J2EE環境下使用JNDI是非常簡單的事,因爲所有的J2EE容器都要實現JNDI服務,所以,在J2EE環境下使用JNDI,與使用 Hashtable也沒有什麼太大區別。只有一點限制,那就是綁定對象時,對象所屬的類必須實現java.io.Serializable接口,這一點也 實在一點也不困難,幾乎所有用到的Java類都實現了這個接口,對於自定義的類,在接口實現列表裏把這個接口加進去也就是了。

下面,我將演示一下如何在J2EE環境下使用JNDI,爲了保證代碼的通用性,我不使用struts之類的框架,而是直接使用標準JSP和Servlet實現。我將該項目的名稱定爲jndi_test

要使用JNDI,需要先到SUN的網站上去下載jndi.jar。

 2.1 JSP

本項目包括5個JSP,功能說明如下:

  • index.jsp:首頁
  • bind.jsp:用於在JNDI中綁定對象
  • bind_result.jsp:綁定對象後的返回頁面
  • lookup.jsp:用於在JNDI中檢索對象
  • lookup_result.jsp:用於顯示檢索對象

本節中用到的JSP代碼如下,代碼都簡單地很,就不多做解釋了。

2.1.1 index.jsp

 > bind an object </ a > 
 > lookup the binded object </ a > 
 </ body > 
 </ html >

2.1.5 lookup_result.jsp

 <% @ page language = " java "  contentType = " text/html; charset=GB18030 " 
     pageEncoding
 = " GB18030 " %> 
 <! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" > 
 < html > 
 < head > 
 < meta  http-equiv ="Content-Type"  content ="text/html; charset=GB18030" > 
 < title > JNDI Test - Lookup result </ title > 
 </ head > 
 < body > 
 <% 
     
 Object  o  =  request.getAttribute( " found_jndi_obj " );
     out.println(o);
 
%> 
 </ body > 
 </ html >

2.2 Servlet

本例包括兩個Servlet,功能說明如下:

  • BindServlet:用於在JNDI服務中綁定一個對象
  • LookupServlet:用於在JNDI服務中取出一個對象

2.2.1 BindServlet.java

 package  lld.test.jndi;
 
 import  java.io.IOException;
 import  java.util.Date;
 
 import  javax.naming.Context;
 import  javax.naming.InitialContext;
 import  javax.servlet.RequestDispatcher;
 import  javax.servlet.ServletContext;
 import  javax.servlet.ServletException;
 import  javax.servlet.http. * ;
 
 public   class  BindServlet  extends  HttpServlet
 {
 
      private   static   final   long  serialVersionUID  =   5219969790998794367L ;
 
     @Override
      protected   void  doGet(HttpServletRequest req, HttpServletResponse resp)
              throws  ServletException, IOException
      {
          this .doPost(req, resp);
     } 
 
     @Override
      protected   void  doPost(HttpServletRequest req, HttpServletResponse resp)
              throws  ServletException, IOException
      {
          try 
          {
             Context jndi_ctx  =   new  InitialContext();
             String key  =   " jndi_object " ;
             jndi_ctx.rebind(key,  new  Date());

         } catch (Exception ex)
          {
             ex.printStackTrace();
         } 
         
         ServletContext context  =   this .getServletContext();
         RequestDispatcher dispatcher  =  context.getRequestDispatcher( " /bind_result.jsp " );
         dispatcher.forward(req, resp);
     } 
     
 }

使用rebind而不是bind綁定對象是因爲,使用bind時,如果已經有對象綁定到該鍵值上,則會拋出異常。

因爲只是示例代碼,所以我只是綁定了一個最簡單的日期對象。

2.2.2 LookupServlet.java

 package  lld.test.jndi;
 
 import  java.io.IOException;
 
 import  javax.naming.Context;
 import  javax.naming.InitialContext;
 import  javax.servlet.RequestDispatcher;
 import  javax.servlet.ServletContext;
 import  javax.servlet.ServletException;
 import  javax.servlet.http.HttpServlet;
 import  javax.servlet.http.HttpServletRequest;
 import  javax.servlet.http.HttpServletResponse;
 
 public   class  LookupServlet  extends  HttpServlet
 {
      private   static   final   long  serialVersionUID  =   6677219828267184673L ;
 
     @Override
      protected   void  doGet(HttpServletRequest req, HttpServletResponse resp)
              throws  ServletException, IOException
      {
          this .doPost(req, resp);
     } 
 
     @Override
      protected   void  doPost(HttpServletRequest req, HttpServletResponse resp)
              throws  ServletException, IOException
      {
          try 
          {
             Context jndi_ctx  =   new  InitialContext();
             String key  =   " jndi_object " ;
             Object o  =  jndi_ctx.lookup(key);
             req.setAttribute( " found_jndi_obj " , o);
         } catch (Exception ex)
          {
             ex.printStackTrace();
         } 
         
         ServletContext context  =   this .getServletContext();
         RequestDispatcher dispatcher  =  context.getRequestDispatcher( " /lookup_result.jsp " );
         dispatcher.forward(req, resp);
     } 
     
 }

2.3 web.xml

在web.xml中,加入了servlet映射

 <? xml version="1.0" encoding="UTF-8" ?> 
 < web-app  id ="WebApp_ID"  version ="2.4"  xmlns ="http://java.sun.com/xml/ns/j2ee"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" > 
      < display-name > jndi_test </ display-name > 
     
      < servlet > 
          < servlet-name > BindServlet </ servlet-name > 
          < servlet-class > lld.test.jndi.BindServlet </ servlet-class > 
      </ servlet > 
      < servlet-mapping > 
          < servlet-name > BindServlet </ servlet-name > 
          < url-pattern > /bind.do </ url-pattern > 
      </ servlet-mapping > 
     
      < servlet > 
          < servlet-name > LookupServlet </ servlet-name > 
          < servlet-class > lld.test.jndi.LookupServlet </ servlet-class > 
      </ servlet > 
     
      < servlet-mapping > 
          < servlet-name > LookupServlet </ servlet-name > 
          < url-pattern > /lookup.do </ url-pattern > 
      </ servlet-mapping > 
     
      < welcome-file-list > 
          < welcome-file > index.jsp </ welcome-file > 
      </ welcome-file-list > 
 </ web-app >

OK,所有的代碼都在這裏了,部署到Tomcat下運行即可。

JNDI 筆記(三) J2SE下使用JNDI

在J2SE下使用JNDI下就顯得困難一些,首先,我們沒有單獨的JNDI服務器可以用,JBoss提供了一個免費的JNP服務,通過配置可以作爲 單獨的JNDI服務器啓用。不過這裏就不這麼麻煩了,如何使用JBOSS作爲JNDI服務器,以後將單獨撰文講述,這裏我使用sun提供的 com.sun.jndi.fscontext.RefFSContextFactory作爲JNDI服務器,其實這是使用文件系統來存儲JNDI對象。 至於如何存儲後文還將專門描述。

爲了在J2SE下使用JNDI,我們首先得到sun的網站上下載3個包,jndi.jar、fscontext.jar和providerutil.jar,前者提供了JNDI服務的接口,後兩者是我們要使用的文件系統作爲JNDI服務器的支持包。

使用RefFSContextFactory,要求綁定的對象必須實現javax.naming.Referencable接口,否則在綁定時將報如下錯誤:

Can only bind References or Referenceable objects

各個JDBC驅動提供商提供的DataSource類都實現了Referencable接口,可以直接使用。不過本着學習的態度,我還是在這裏演示一下如何實現Referencable接口。

這個如何實現將在後文結合代碼詳細介紹。本例包括4個類,說明如下:

  • BindedClass:自定義的實現Referenceable接口的類
  • BindedClassFactory:工廠類,能夠把一個Reference對象轉換爲BindedClass對象
  • Bind:測試類,用於在JNDI中綁定對象
  • Loopup:測試類,用於從JNDI中獲取對象

3.1 BindedClass和BindedClassFactory

3.1.1 BindedClass

 package  lld.test.jndi;
 
 import  javax.naming.NamingException;
 import  javax.naming.Reference;
 import  javax.naming.Referenceable;
 import  javax.naming.StringRefAddr;
 
 public   class  BindedClass  implements  Referenceable 
 {
      public  String value; 
     
      public  BindedClass()
      {
     } 
     
     @Override
      public  Reference getReference()  throws  NamingException
      {
         Reference r  =   new  Reference( this .getClass().getName(), BindedClassFactory. class .getName(),  null );
         r.add( new  StringRefAddr( " value " ,  this .getValue()));
          return  r;
     } 
 
      public  String getValue()
      {
          return  value;
     } 
 
      public   void  setValue(String value)
      {
          this .value  =  value;
     } 
 
 }

3.1.2 BindedClassFactory

 package  lld.test.jndi;
 
 import  java.util.Hashtable;
 
 import  javax.naming. * ;
 import  javax.naming.spi. * ;
 
 public   class  BindedClassFactory  implements  ObjectFactory
 {
     @Override
      public  Object getObjectInstance(Object obj, Name name, Context nameCtx,

。。。}


¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥

Tomcat6.0連接池配置1
 1.配置tomcat下的conf下的context.xml文件,在之間添加連接池配置: <Resource name="jdbc/oracle"

       auth="Container"          

       type="javax.sql.DataSource"          

       driverClassName="oracle.jdbc.driver.OracleDriver"          

       url=" jdbc:oracle:thin:@host:port:databse"          

       username=" user "          

       password="password"          

       maxActive="100"          

       maxIdle="30"          

      maxWait="10000" />  

2.配置你的應用下的web.xml中的之間加入:

<resource-ref>          

    <description>DB Connection</description>          

    <res-ref-name>jdbc/oracle</res-ref-name>          

    <res-type>javax.sql.DataSource</res-type>          

    <res-auth>Container</res-auth>          

  </resource-ref>    

3.把連接數據庫的第三方驅動放到common/lib下面就ok了 


 

Tomcat6.0 連接池的配置2

配置步驟如下:1.Tomcat 6的配置和以前的不同了,不推薦在server.xml中進行配置,而是在%Tomcat_Home%\webapps\yourApp\META-INF \context.xml中進行配置纔是更好的方法。而不是以前版本%Tomcat_Home%\conf下的context.xml文件。這樣就可以在不同的web應用下單獨配置連接池了,且Tomcat會自動重載。當然你也可以更改%Tomcat_Home%\conf下的context.xml文件,將所有web應用下的連接池進行統一配置。

2.將代碼修改如下:

view plaincopy to clipboardprint?
<Context reloadable="true">  
    <WatchedResource>WEB-INF/web.xml</WatchedResource>  
    <Resource name="jdbc/oracleds" auth="Container" type="javax.sql.DataSource"    
    maxActive="100"    
    maxIdle="30"  
    maxWait="10000"  
    username="scott"    
    password="tiger"  
    driverClassName="oracle.jdbc.driver.OracleDriver"  
    url="jdbc:oracle:thin:@localhost:1521:ora9"/>  
</Context>  
<Context reloadable="true">
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
 <Resource name="jdbc/oracleds" auth="Container" type="javax.sql.DataSource" 
 maxActive="100" 
 maxIdle="30"
 maxWait="10000"
 username="scott" 
 password="tiger"
 driverClassName="oracle.jdbc.driver.OracleDriver"
 url="jdbc:oracle:thin:@localhost:1521:ora9"/>
</Context>

name 爲當前數據源JNDI的名字,可以隨意設定;

auth 爲驗證方式;

type 資源類型;

driverClassName 爲Oracle驅動引用;

maxActiv 爲連接池最大激活的連接數,設爲0表示無限制;

maxIdle 爲連接池最大空閒的連接數,數據庫連接的最大空閒時間。超過空閒時間,

            數據庫連接將被標記爲不可用,然後被釋放。設爲0表示無限制;

maxWait 爲連接最大的等待時間,單位毫秒,如果超過此時間將接到異常。設爲-1

              表示無限制。;

username 爲oracle數據庫的一個用戶名;

password 爲username的密碼;

url 爲連接oracle的連接地址;

注:本人嘗試將代碼“driverClassName="oracle.jdbc.driver.OracleDriver"”改爲“driverClassName="oracle.jdbc.OracleDriver"”程序依然運行正常,剛開始以爲老師的代碼有問題

3.在程序中的調用形式爲:

view plaincopy to clipboardprint?
Context context = new InitialContext();   
DataSource ds = (DataSource)context.lookup("java:/comp/env/jdbc/oracleds");   
Connection conn = ds.getConnection();  
Context context = new InitialContext();
DataSource ds = (DataSource)context.lookup("java:/comp/env/jdbc/oracleds");
Connection conn = ds.getConnection();

注:“java:/comp/env/jdbc/oracleds”紅色標記文字爲步驟1裏設置的Resource name

則可以將建立connection的方式以上述形式取代傳統方式:

view plaincopy to clipboardprint?
String driver = "oracle.jdbc.driver.OracleDriver";   
String url = "jdbc:oracle:thin:@localhost:1521:ora9";   
String username = "scott";   
String password = "tiger";   
Class.forName(driver);   
Connection conn = DriverManager.getConnection(url, username, password);  
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@localhost:1521:ora9";
String username = "scott";
String password = "tiger";
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, username, password);

4.另外還需將用到的jdbc驅動類庫導入到%Tomcat_Home%\lib目錄下

否則會拋出如下異常:
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot load JDBC driver class 'oracle.jdbc.driver.OracleDriver'

依上述步驟就能成功的配置Tomcat6.0 連接池,還有網友貼文說需

在web.xml文件中的web-app節點下加入如下代碼形式:
<resource-ref>
<res-ref-name>jdbc/myoracle</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>

因本人未添加此項,程序依然正確,故本人認爲此步驟爲非必要項

今天需要在另一臺機器上重新部署系統,重新設置db的連接池。當我把tomcat拷貝到那臺機器,並且修改META-INF\context.xml,然後重新啓動tomcat,但發現系統連接的仍然是老的db。再次檢查了META-INF\context.xml文件,確信了這個文件已經正確設置db連接了,這也說明這個文件並沒有真正起作用。查看了tomcat下conf\context.xml也沒有設置db的連接池。那是哪個文件在起作用呢?折騰了辦法,後來發現tomcat在conf\Catalina\localhost下生成了一個和原來META-INF\context.xml相同內容的文件,懷疑一定是這個文件在起作用?刪除conf\Catalina\localhost目錄,重啓tomcat,問題消失。

Tomcat6.0 連接池的配置3

 

不管是tomcat5,Tomcat5.5或Tomcat6.0. 用下面的這兩中方法配置連接池,都可以成功.

 

 1. 應該算是全局的連接池的配置

  

     (1).不管是tomcat5 還是tomcat6 ,都首先找到Tomcat目錄下面的conf目錄中的server.xml文件.

           找到<GlobalNamingResources> </GlobalNamingResources>這對標籤.

        將這樣的一段配置加到標籤中間.

        <Resource    

    name="jdbc/TestDB"    

    auth="Container"           

                type="javax.sql.DataSource"  

    driverClassName="com.mysql.jdbc.Driver"    

url="jdbc:mysql://localhost:3306/test?autoReconnect=true"  

        maxActive="50"    

    maxldle="10"    

    maxWait="5000"  

    username="root"  

password="admin" />  

當然,樣例是使用 MYSQL配置, 根據不同的需要,將url,driverClassName,username,passsword等參數改變就行.

         然後再找到和server.xml同目錄下面的context.xml文件.

   在<Context></Context>標籤中添加如下配置.

<ResourceLink global="jdbc/TestDB" name="jdbc/TestDB" type="javax.sql.DataSource"/>  

global="jdbc/TestDB" 中的參數值("jdbc/TestDB")必須和上一段<Resource >配置中的name屬性的值保持一樣.

     name="jdbc/TestDB" 這個可以隨便取,但是在程序中調用的時候,就應該與name的值保持一致.

     到這裏,連接池已經配置好啦

寫個jsp測試

<%@ page language="java" pageEncoding="gbk"%>   

<%@page import="java.sql.Connection"%>   

<%@page import="javax.naming.Context"%>   

<%@page import="javax.naming.InitialContext"%>   

<%@page import="javax.sql.DataSource"%>   

<%@page import="java.sql.Statement"%>   

<%@page import="java.sql.ResultSet"%>   

<%    

   //連接池的獲取   

    Connection conn = null;   

    DataSource ds = null;   

    ResultSet rs  =null;   

    Statement stmt = null;   

    Context initCtx = new InitialContext();   

    ds =(DataSource)initCtx.lookup("java:comp/env/jdbc/TestDB");   

   if(ds!=null){   

        out.println("已經獲得DataSource!");    

        out.println("<br>");   

        conn = ds.getConnection();   

       try{   

        stmt = conn.createStatement();   

        String sql ="select * from tree_table";   

        rs = stmt.executeQuery(sql);   

        out.println("以下是從數據庫中讀取出來的數據:<br>");   

            while(rs.next()){   

                out.println("<br>");   

                out.println(rs.getString("nodeName"));   

            }   

       }catch(Exception ex){   

         ex.printStackTrace();   

       }finally{   

          conn.close();   

          rs.close();   

          stmt.close();   

       }   

   }   

%>  

在這ds =(DataSource)initCtx.lookup("java:comp/env/jdbc/TestDB");這句代碼中的jdbc/TestDB必須和

    <ResourceLink global="jdbc/TestDB" name="jdbc/TestDB" ........ />中的name 屬性保持一樣.

     "lookup("java:comp/env/..."這都是固定寫法.

  

    2.  應該算是局部的連接池的配置吧.(針對工程而言)

       本身我們的工程中META-INF 中,沒有context.xml文件,

       例如 :E:\apache-tomcat-5.5.16\webapps\myproj\META-INF\

     

       此時我們可以在META-INF目錄下面新建一個context.xml文件.

      裏面寫下如下的配置,具體的配置參數,按需改變.

Xml代碼

<?xml version="1.0" encoding="UTF-8"?>  

<Context reloadable="true" crossContext="true">  

<Resource    

name="jdbc/TestDB"    

auth="Container"    

type="javax.sql.DataSource"  

driverClassName="com.mysql.jdbc.Driver"    

url="jdbc:mysql://localhost:3306/test?autoReconnect=true"  

maxActive="50"    

maxldle="10"    

maxWait="5000"  

username="root"  

password="admin"    

/>  

</Context>  

這樣子,連接池,也就配置好啦,並不需要修改tomcat裏面的文件。僅僅在我們的工程中的META-INF目錄加入一個context.xml配置文件就好啦.換tomcat版本,更容易.

 

 注:也許你認爲配置這邊文章很簡單,配置數據源連接池也很簡單.但是對於初學者來說,可能是困窘他好久的問題.這方面以前我深有體會.大家都是這樣過來的.  僅供參考.






















發佈了34 篇原創文章 · 獲贊 62 · 訪問量 182萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章