1.在Tomcat中添加JNDI資料來源
建議用Tomcat的Adiminstration添加。在預設情況下,Tomcat沒有安裝administration組件,詳細安裝步驟請參考《Install the component Admin for tomcat》。
登陸http://localhost:8080/admin, 進入Resources -> Data Sources -> Create New Data Source
設定JNDI參數:(這裡以MySql為例)
JNDI Name:jdbc/mysql(JNDI 名隨便起)
Data Source URL:jdbc:mysql://localhost:3306/test(這裡test是資料庫名,當然後面還可以帶其他參數,如:jdbc: mysql://localhost:3306/test?user=root&password=&useUnicode=true& characterEncoding=gbk&autoReconnect=true&failOverReadOnly=false)
JDBC Driver Class:com.mysql.jdbc.Driver (要把相應的驅動jar包放到$TOMCAT_HOME$/common/lib)
User Name:root (使用者名稱)
Password:***** (密碼)
Max. Active Connections:4
Max. Idle Connections:2
Max. Wait for Connection:5000
2.在Web項目中配置resouce-ref
在項目的web.xml的根節點下添加以下內容:
<resource-ref>
<res-ref-name>jdbc/mysql</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
注意:這裡res-ref-name必須與在tomcat中設定的JNDI Name:jdbc/mysql(JNDI 名隨便起)一致。
3.設定$TOMCAT_HOME$/conf/server.xml
因為TOMCAT不會自動將Data Source Resource資訊加到Context中,所以經常會忽略這一步
當前server.xml的內容為:
<?xml version="1.0" encoding="UTF-8"?>
<Server>
<Listener className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener"/>
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener"/>
<GlobalNamingResources>
<Environment
name="simpleValue"
type="java.lang.Integer"
value="30"/>
<Resource
auth="Container"
description="User database that can be updated and saved"
name="UserDatabase"
type="org.apache.catalina.UserDatabase"
pathname="conf/tomcat-users.xml"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"/>
<Resource
name="jdbc/mysql"
type="javax.sql.DataSource"
password="123456"
driverClassName="com.mysql.jdbc.Driver"
maxIdle="2"
maxWait="5000"
username="root"
url="jdbc:mysql://localhost:3306/test"
maxActive="4"/>
</GlobalNamingResources>
<Service
name="Catalina">
<Connector
port="8080"
redirectPort="8443"
minSpareThreads="25"
connectionTimeout="60000"
connectionLinger="-1"
serverSoTimeout="0"
maxSpareThreads="75"
maxThreads="150"
tcpNoDelay="true"
maxHttpHeaderSize="8192">
</Connector>
<Connector
port="8009"
redirectPort="8443"
protocol="AJP/1.3">
</Connector>
<Engine
defaultHost="localhost"
name="Catalina">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"/>
<Host
appBase="webapps"
name="localhost">
<Context
docBase="/test"
path="/test"
reloadable="true"
debug="5"
crossContext="true">
<Resource
name="jdbc/mysql"
type="javax.sql.DataSource"
password="123456"
maxIdle="2"
maxWait="5000"
username="root"
maxActive="4"
/>
</Context>
</Host>
</Engine>
</Service>
</Server>
如果不更改該server.xml檔案,使用jdbc/mysql時拋exception Cannot create JDBC driver of class '' for connect URL 'null'。
留意代碼最後的resource
<Context
docBase="/test"
path="/test"
reloadable="true"
debug="5"
crossContext="true">
<Resource
name="jdbc/mysql"
type="javax.sql.DataSource"
password="123456"
maxIdle="2"
maxWait="5000"
username="root"
maxActive="4"
/>
</Context>
發現在<Resource />標籤中沒包含屬性driverClassName和url,這是拋Exception Cannot create JDBC driver of class '' for connect URL 'null'的原因。
我們只需要將<GlobalNamingResources></GlobalNamingResources>中相應的Resource
<Resource
name="jdbc/mysql"
type="javax.sql.DataSource"
password="123456"
driverClassName="com.mysql.jdbc.Driver"
maxIdle="2"
maxWait="5000"
username="root"
url="jdbc:mysql://localhost:3306/test"
maxActive="4"/>
替換掉Context下的resource即可。
更改後的server.xml檔案內容為:
<?xml version="1.0" encoding="UTF-8"?>
<Server>
<Listener className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener"/>
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener"/>
<GlobalNamingResources>
<Environment
name="simpleValue"
type="java.lang.Integer"
value="30"/>
<Resource
auth="Container"
description="User database that can be updated and saved"
name="UserDatabase"
type="org.apache.catalina.UserDatabase"
pathname="conf/tomcat-users.xml"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"/>
<Resource
name="jdbc/mysql"
type="javax.sql.DataSource"
password="123456"
driverClassName="com.mysql.jdbc.Driver"
maxIdle="2"
maxWait="5000"
username="root"
url="jdbc:mysql://localhost:3306/test"
maxActive="4"/>
</GlobalNamingResources>
<Service
name="Catalina">
<Connector
port="8080"
redirectPort="8443"
minSpareThreads="25"
connectionTimeout="60000"
connectionLinger="-1"
serverSoTimeout="0"
maxSpareThreads="75"
maxThreads="150"
tcpNoDelay="true"
maxHttpHeaderSize="8192">
</Connector>
<Connector
port="8009"
redirectPort="8443"
protocol="AJP/1.3">
</Connector>
<Engine
defaultHost="localhost"
name="Catalina">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"/>
<Host
appBase="webapps"
name="localhost">
<Context
docBase="/test"
path="/test"
reloadable="true"
debug="5"
crossContext="true">
<Resource
name="jdbc/mysql"
type="javax.sql.DataSource"
password="123456"
driverClassName="com.mysql.jdbc.Driver"
maxIdle="2"
maxWait="5000"
username="root"
url="jdbc:mysql://localhost:3306/test"
maxActive="4"/>
</Context>
</Host>
</Engine>
</Service>
</Server>
4.在java代碼中使用JNDI資源獲得DataSource
javax.naming.InitialContext ctx = new javax.naming.InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/mysql");
Connection conn = ds.getConnection();
該代碼在JDK1.5下測試通過
在一些資料中提到,在JDK1.5以前的版本可以通過
DataSource ds = (DataSource) ctx.lookup("jdbc/mysql");
獲得DataSource。
我沒測試過該代碼。
上述代碼在J2EE伺服器環境下工作得很好,但是在main()中就會報一個NoInitialContextException。
之所以有NoInitialContextException是因為無法從System.properties中獲得必要的JNDI參數,在伺服器環境下,伺服器啟動時就把這些參數放到System.properties中。
所以可以通過以下方法解決:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL,"t3://localhost:7001");
InitialContext ctx = new InitialContext(env);
或
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
System.setProperty(Context.PROVIDER_URL, "rmi://localhost:3306/test");
System.setProperty(Context.SECURITY_PRINCIPAL, "root");
System.setProperty(Context.SECURITY_CREDENTIALS, "123456");
以上代碼建議改為在設定檔中配置
java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
java.naming.provider.url=rmi://localhost:3306/test
java.naming.security.principal=user
java.naming.security.credentials=password