JNDI数据源的配置
一、數據源的由來
在Java開發中,使用JDBC操作數據庫的四個步驟如下:
①加載數據庫驅動程序(Class.forName("數據庫驅動類");)?? ?、谶B接數據庫(Connection con? = DriverManager.getConnection();)
?? ③操作數據庫(PreparedStatement stat = con.prepareStatement(sql);stat.executeQuery();)
?? ?、荜P閉數據庫,釋放連接(con.close();)
也就是說,所有的用戶都需要經過此四步進行操作,但是這四步之中有三步(①加載數據庫驅動程序、②連接數據庫、④關閉數據庫,釋放連接)對所有人都是一樣的,而所有人只有在操作數據庫上是不一樣,那么這就造成了性能的損耗。
那么最好的做法是,準備出一個空間,此空間里專門保存著全部的數據庫連接,以后用戶用數據庫操作的時候不用再重新加載驅動、連接數據庫之類的,而直接從此空間中取走連接,關閉的時候直接把連接放回到此空間之中。
那么此空間就可以稱為連接池(保存所有的數據庫連接),但是如果要想實現此空間的話,則必須有一個問題要考慮?
? ? 1、?如果沒有任何一個用戶使用連接,那么那么應該維持一定數量的連接,等待用戶使用。
?? 2、?如果連接已經滿了,則必須打開新的連接,供更多用戶使用。
?? 3、?如果一個服務器就只能有100個連接,那么如果有第101個人過來呢?應該等待其他用戶釋放連接
?? 4、?如果一個用戶等待時間太長了,則應該告訴用戶,操作是失敗的。
? 如果直接用程序實現以上功能,則會比較麻煩,所以在Tomcat 4.1.27之后,在服務器上就直接增加了數據源的配置選項,直接在服務器上配置好數據源連接池即可。在J2EE服務器上保存著一個數據庫的多個連接。每一個連接通過DataSource可以找到。DataSource被綁定在了JNDI樹上(為每一個DataSource提供一個名字)客戶端通過名稱找到在JNDI樹上綁定的DataSource,再由DataSource找到一個連接。如下圖所示: 那么在以后的操作中,除了數據庫的連接方式不一樣之外,其他的所有操作都一樣,只是關閉的時候不是徹底地關閉數據庫,而是把數據庫的連接放回到連接池中去。 如果要想使用數據源的配置,則必須配置虛擬目錄,因為此配置是在虛擬目錄之上起作用的。需要注意的是,如果要想完成以上的功能,在Tomcat服務器上一定要有各個數據庫的驅動程序。
二、JNDI+Tomcat配置數據源的兩種方式
2.1、全局jndi配置
此種配置需要在server.xml中配置數據源,具體的配置步驟如下:
1、在tomcat服務器的lib目錄下加入數據庫連接的驅動jar包
2、修改tomcat服務器的conf目錄下server.xml配置文件
打開server.xml配置文件,可以看到里面自帶的一個全局JNDI配置,如下圖所示:
編輯server.xml文件,添加全局JNDI數據源配置,配置如下:
1 <!-- Global JNDI resources2 Documentation at /docs/jndi-resources-howto.html3 -->4 <GlobalNamingResources>5 <!-- Editable user database that can also be used by6 UserDatabaseRealm to authenticate users7 -->8 <Resource name="UserDatabase" auth="Container"9 type="org.apache.catalina.UserDatabase" 10 description="User database that can be updated and saved" 11 factory="org.apache.catalina.users.MemoryUserDatabaseFactory" 12 pathname="conf/tomcat-users.xml" /> 13 <!-- 14 |- name:表示以后要查找的名稱。通過此名稱可以找到DataSource,此名稱任意更換,但是程序中最終要查找的就是此名稱, 15 為了不與其他的名稱混淆,所以使用jdbc/oracle,現在配置的是一個jdbc的關于oracle的命名服務。 16 |- auth:由容器進行授權及管理,指的用戶名和密碼是否可以在容器上生效 17 |- type:此名稱所代表的類型,現在為javax.sql.DataSource 18 |- maxActive:表示一個數據庫在此服務器上所能打開的最大連接數 19 |- maxIdle:表示一個數據庫在此服務器上維持的最小連接數 20 |- maxWait:最大等待時間。10000毫秒 21 |- username:數據庫連接的用戶名 22 |- password:數據庫連接的密碼 23 |- driverClassName:數據庫連接的驅動程序 24 |- url:數據庫連接的地址 25 --> 26 <!--配置Oracle數據庫的JNDI數據源--> 27 <Resource 28 name="jdbc/oracle" 29 auth="Container" 30 type="javax.sql.DataSource" 31 maxActive="100" 32 maxIdle="30" 33 maxWait="10000" 34 username="lead_oams" 35 password="p" 36 driverClassName="oracle.jdbc.driver.OracleDriver" 37 url="jdbc:oracle:thin:@192.168.1.229:1521:lead"/> 38 39 <!--配置MySQL數據庫的JNDI數據源--> 40 <Resource 41 name="jdbc/mysql" 42 auth="Container" 43 type="javax.sql.DataSource" 44 maxActive="100" 45 maxIdle="30" 46 maxWait="10000" 47 username="root" 48 password="root" 49 driverClassName="com.mysql.jdbc.Driver" 50 url="jdbc:mysql://192.168.1.144:3306/leadtest?useUnicode=true&characterEncoding=utf-8"/> 51 52 <!--配置SQLServer數據庫的JNDI數據源--> 53 <Resource 54 name="jdbc/sqlserver" 55 auth="Container" 56 type="javax.sql.DataSource" 57 maxActive="100" 58 maxIdle="30" 59 maxWait="10000" 60 username="sa" 61 password="p@ssw0rd" 62 driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" 63 url="jdbc:sqlserver://192.168.1.51:1433;DatabaseName=demo"/> 64 65 </GlobalNamingResources>經過以上的兩個步驟,全局JNDI數據源就配置好了,在上述的server.xml文件中,分別配置了Oracle、MySQL、SQLServer這三種數據庫的全局JNDI數據源。
2.2、全局jndi數據源測試
1、創建一個JNDI測試項目JNDITest,在web.xml中添加JNDI配置的資源引用
web.xml的配置如下:
<?xml version="1.0" encoding="UTF-8"?>2 <web-app version="2.5" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">7 <welcome-file-list>8 <welcome-file>index.jsp</welcome-file>9 </welcome-file-list> 10 11 <!-- 12 JNDI配置的資源引用: 13 ? res-ref-name:表示引用資源的名稱 14 ? res-type:此資源對應的類型為javax.sql.DataSource 15 ? res-auth:容器授權管理 16 --> 17 <!--Oracle數據庫JNDI數據源引用 --> 18 <resource-ref> 19 <description>Oracle DB Connection</description> 20 <res-ref-name>oracleDataSource</res-ref-name> 21 <res-type>javax.sql.DataSource</res-type> 22 <res-auth>Container</res-auth> 23 </resource-ref> 24 25 <!--MySQL數據庫JNDI數據源引用 --> 26 <resource-ref> 27 <description>MySQL DB Connection</description> 28 <res-ref-name>mysqlDataSource</res-ref-name> 29 <res-type>javax.sql.DataSource</res-type> 30 <res-auth>Container</res-auth> 31 </resource-ref> 32 33 <!--SQLServer數據庫JNDI數據源引用 --> 34 <resource-ref> 35 <description>SQLServer DB Connection</description> 36 <res-ref-name>sqlserverDataSource</res-ref-name> 37 <res-type>javax.sql.DataSource</res-type> 38 <res-auth>Container</res-auth> 39 </resource-ref> 40 41 </web-app>2、映射JNDITest項目的虛擬目錄
在tomcat的\conf\Catalina\localhost下(沒有目錄就新建)創建一個xml文件,文件名必須和項目名相同,測試JNDI數據源的web項目的項目名稱是:JNDITest,所以xml文件的命名就叫JNDITest.xml,如下圖所示:
編輯JNDITest.xml,配置如下:
1 <?xml version="1.0" encoding="UTF-8"?>2 <!--3 jndi配置方法(tomcat):4 將此文件放置在tomcat\conf\Catalina\localhost下(沒有目錄就新建)5 -->6 <!--映射JNDITest項目的虛擬目錄-->7 <Context docBase="D:/MyEclipse8.5/workspace/JNDITest/WebRoot" debug="0" reloadable="false">8 <!--引用Oracle數據庫的JNDI數據源-->9 <ResourceLink name="oracleDataSource" global="jdbc/oracle" type="javax.sql.DataSource"/> 10 <!--引用mysql數據庫的JNDI數據源--> 11 <ResourceLink name="mysqlDataSource" global="jdbc/mysql" type="javax.sql.DataSource"/> 12 <!--引用sqlserver數據庫的JNDI數據源--> 13 <ResourceLink name="sqlserverDataSource" global="jdbc/sqlserver" type="javax.sql.DataSource"/> 14 </Context>3、測試從JNDI數據源獲取數據庫連接
配置完數據源連接池之后,就可以按照以下的步驟進行訪問:
? 初始化名稱查找上下文?? ? 通過JNDI名稱找到DataSource
?? ? 通過DataSource取得一個連接
? ?? 操作數據庫
?? ? 關閉數據庫,關閉的時候是將連接放回到連接池之中
jsp測試頁面代碼如下:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <%@ page import="java.sql.*,javax.sql.*,javax.naming.*" %>3 4 <!DOCTYPE HTML>5 <html>6 <head>7 <title>JNDI數據源測試</title>8 </head>9 10 <body>11 <%12 Connection connOracle = null;13 try {14 //1、初始化名稱查找上下文15 Context ctx = new InitialContext();16 //InitialContext ctx = new InitialContext();亦可 17 //2、通過JNDI名稱找到DataSource,對名稱進行定位java:comp/env是必須加的,后面跟的是DataSource名18 /*19 DataSource名在web.xml文件中的<res-ref-name>oracleDataSource</res-ref-name>進行了配置20 <!--Oracle數據庫JNDI數據源引用 -->21 <resource-ref>22 <description>Oracle DB Connection</description>23 <res-ref-name>oracleDataSource</res-ref-name>24 <res-type>javax.sql.DataSource</res-type>25 <res-auth>Container</res-auth>26 </resource-ref>27 */28 DataSource ds = (DataSource)ctx.lookup("java:comp/env/oracleDataSource");29 //3、通過DataSource取得一個連接30 connOracle = ds.getConnection();31 out.println("Oracle Connection pool connected !!");32 //4、操作數據庫33 } catch (NamingException e) {34 System.out.println(e.getMessage());35 } catch (SQLException e) {36 e.printStackTrace();37 } finally {38 //5、關閉數據庫,關閉的時候是將連接放回到連接池之中39 connOracle.close();40 }41 %>42 <hr/>43 <%44 Connection connMySQL = null;45 try {46 //1、初始化名稱查找上下文47 Context ctx = new InitialContext();48 //InitialContext ctx = new InitialContext();亦可 49 //2、通過JNDI名稱找到DataSource,對名稱進行定位java:comp/env是必須加的,后面跟的是DataSource名50 /*51 DataSource名在web.xml文件中的<res-ref-name>mysqlDataSource</res-ref-name>進行了配置52 <!--MySQL數據庫JNDI數據源引用 -->53 <resource-ref>54 <description>MySQL DB Connection</description>55 <res-ref-name>mysqlDataSource</res-ref-name>56 <res-type>javax.sql.DataSource</res-type>57 <res-auth>Container</res-auth>58 </resource-ref>59 */60 DataSource ds = (DataSource)ctx.lookup("java:comp/env/mysqlDataSource");61 //3、通過DataSource取得一個連接62 connMySQL = ds.getConnection();63 out.println("MySQL Connection pool connected !!");64 //4、操作數據庫65 } catch (NamingException e) {66 System.out.println(e.getMessage());67 } catch (SQLException e) {68 e.printStackTrace();69 } finally {70 //5、關閉數據庫,關閉的時候是將連接放回到連接池之中71 connMySQL.close();72 }73 %>74 <hr/>75 <%76 Connection connSQLServer = null;77 try {78 //1、初始化名稱查找上下文79 Context ctx = new InitialContext();80 //InitialContext ctx = new InitialContext();亦可 81 //2、通過JNDI名稱找到DataSource,對名稱進行定位java:comp/env是必須加的,后面的是DataSource名82 /*83 DataSource名在web.xml文件中的<res-ref-name>sqlserverDataSource</res-ref-name>進行了配置84 <!--SQLServer數據庫JNDI數據源引用 -->85 <resource-ref>86 <description>SQLServer DB Connection</description>87 <res-ref-name>sqlserverDataSource</res-ref-name>88 <res-type>javax.sql.DataSource</res-type>89 <res-auth>Container</res-auth>90 </resource-ref>91 */92 DataSource ds = (DataSource)ctx.lookup("java:comp/env/sqlserverDataSource");93 //3、通過DataSource取得一個連接94 connSQLServer = ds.getConnection();95 out.println("SQLServer Connection pool connected !!");96 //4、操作數據庫97 } catch (NamingException e) {98 System.out.println(e.getMessage());99 } catch (SQLException e) { 100 e.printStackTrace(); 101 } finally { 102 //5、關閉數據庫,關閉的時候是將連接放回到連接池之中 103 connSQLServer.close(); 104 } 105 %> 106 </body> 107 </html>運行結果如下:
除了可以在Jsp頁面中編寫java代碼測試JNDI數據源連接之外,還有一種比較簡單的方式就是使用JSTL標簽庫提供的sql標簽進行測試,測試代碼如下:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <%--引入JSTL標簽庫 --%>3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>4 <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>5 <!DOCTYPE HTML>6 <html>7 <head>8 <title>JNDI數據源連接測試</title>9 </head> 10 11 <body> 12 <h3>Oracle JNDI數據源測試</h3> 13 <%--使用sql:query標簽發送SQL語句去數據庫查詢數據,查詢的結果集保存到rs變量當中,dataSource屬性指明使用的數據源--%> 14 <sql:query var="rs" dataSource="oracleDataSource"> 15 <%--Oracle JNDI數據源測試 SQL--%> 16 SELECT * FROM LEAD_OAMS_DBSOURCES 17 </sql:query> 18 <%--使用c:forEach標簽遍歷查詢結果集rs中的每一行--%> 19 <c:forEach var="row" items="${rs.rows}"> 20 <%--${row.字段名}獲取字段的值--%> 21 ${row.RESOURCEID}---${row.DBSOURCE_NAME}---${row.DBSOURCE_TYPE}<br/> 22 </c:forEach> 23 <hr/> 24 <h3>MySQL JNDI數據源測試</h3> 25 <%--使用sql:query標簽發送SQL語句去數據庫查詢數據,查詢的結果集保存到rs變量當中,dataSource屬性指明使用的數據源--%> 26 <sql:query var="rs" dataSource="mysqlDataSource"> 27 <%--MySQL JNDI數據源測試 SQL--%> 28 select * from ld_user 29 </sql:query> 30 <%--使用c:forEach標簽遍歷查詢結果集rs中的每一行--%> 31 <c:forEach var="row" items="${rs.rows}"> 32 <%--${row.字段名}獲取字段的值--%> 33 ${row.id}---${row.username}---${row.password}<br/> 34 </c:forEach> 35 <hr/> 36 <h3>SQLServer JNDI數據源測試</h3> 37 <%--使用sql:query標簽發送SQL語句去數據庫查詢數據,查詢的結果集保存到rs變量當中,dataSource屬性指明使用的數據源--%> 38 <sql:query var="rs" dataSource="sqlserverDataSource"> 39 <%--SQLServer JNDI數據源測試 SQL--%> 40 select * from t_demo 41 </sql:query> 42 <%--使用c:forEach標簽遍歷查詢結果集rs中的每一行--%> 43 <c:forEach var="row" items="${rs.rows}"> 44 <%--${row.字段名}獲取字段的值--%> 45 ${row.id}---${row.time}<br/> 46 </c:forEach> 47 </body> 48 </html>運行結果如下:
2.3、非全局jndi配置
非全局JNDI數據源是針對某一個Web項目配置的數據源,具體的配置步驟如下:
? 1、在tomcat服務器的lib目錄下加入數據庫連接的驅動jar包
2、針對具體的web項目映射虛擬目錄,然后在虛擬目錄映射的配置文件中配置JNDI數據源
還是以上面的JNDITest項目為例子進行說明
在tomcat目錄下的\conf\Catalina\localhost目錄下創建一個JNDITest.xml文件,如下圖所示:
編輯JNDITest.xml文件,添加對JNDITest項目的虛擬目錄的映射和JNDI數據源的配置
1 <?xml version="1.0" encoding="UTF-8"?>2 <!--3 jndi配置方法(tomcat):4 將此文件放置在tomcat\conf\Catalina\localhost下(沒有目錄就新建)5 -->6 7 <Context docBase="D:/MyEclipse8.5/workspace/JNDITest/WebRoot" debug="0" reloadable="false">8 <!--9 |- name:表示以后要查找的名稱。通過此名稱可以找到DataSource,此名稱任意更換,但是程序中最終要查找的就是此名稱, 10 為了不與其他的名稱混淆,所以使用jdbc/oracle,現在配置的是一個jdbc的關于oracle的命名服務。 11 |- auth:由容器進行授權及管理,指的用戶名和密碼是否可以在容器上生效 12 |- type:此名稱所代表的類型,現在為javax.sql.DataSource 13 |- maxActive:表示一個數據庫在此服務器上所能打開的最大連接數 14 |- maxIdle:表示一個數據庫在此服務器上維持的最小連接數 15 |- maxWait:最大等待時間。10000毫秒 16 |- username:數據庫連接的用戶名 17 |- password:數據庫連接的密碼 18 |- driverClassName:數據庫連接的驅動程序 19 |- url:數據庫連接的地址 20 --> 21 <!--配置Oracle數據庫的JNDI數據源--> 22 <Resource 23 name="oracleDataSource" 24 auth="Container" 25 type="javax.sql.DataSource" 26 maxActive="100" 27 maxIdle="30" 28 maxWait="10000" 29 username="lead_oams" 30 password="p" 31 driverClassName="oracle.jdbc.driver.OracleDriver" 32 url="jdbc:oracle:thin:@192.168.1.229:1521:lead"/> 33 34 <!--配置MySQL數據庫的JNDI數據源--> 35 <Resource 36 name="mysqlDataSource" 37 auth="Container" 38 type="javax.sql.DataSource" 39 maxActive="100" 40 maxIdle="30" 41 maxWait="10000" 42 username="root" 43 password="root" 44 driverClassName="com.mysql.jdbc.Driver" 45 url="jdbc:mysql://192.168.1.144:3306/leadtest?useUnicode=true&characterEncoding=utf-8"/> 46 47 <!--配置SQLServer數據庫的JNDI數據源--> 48 <Resource 49 name="sqlserverDataSource" 50 auth="Container" 51 type="javax.sql.DataSource" 52 maxActive="100" 53 maxIdle="30" 54 maxWait="10000" 55 username="sa" 56 password="p@ssw0rd" 57 driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" 58 url="jdbc:sqlserver://192.168.1.51:1433;DatabaseName=demo"/> 59 </Context>3、在web項目的web.xml文件中引用配置好的JNDI數據源
1 <!-- 2 JNDI配置的資源引用:3 ? res-ref-name:表示引用資源的名稱4 ? res-type:此資源對應的類型為javax.sql.DataSource5 ? res-auth:容器授權管理6 -->7 <!--Oracle數據庫JNDI數據源引用 -->8 <resource-ref>9 <description>Oracle DB Connection</description> 10 <res-ref-name>oracleDataSource</res-ref-name> 11 <res-type>javax.sql.DataSource</res-type> 12 <res-auth>Container</res-auth> 13 </resource-ref> 14 15 <!--MySQL數據庫JNDI數據源引用 --> 16 <resource-ref> 17 <description>MySQL DB Connection</description> 18 <res-ref-name>mysqlDataSource</res-ref-name> 19 <res-type>javax.sql.DataSource</res-type> 20 <res-auth>Container</res-auth> 21 </resource-ref> 22 23 <!--SQLServer數據庫JNDI數據源引用 --> 24 <resource-ref> 25 <description>SQLServer DB Connection</description> 26 <res-ref-name>sqlserverDataSource</res-ref-name> 27 <res-type>javax.sql.DataSource</res-type> 28 <res-auth>Container</res-auth> 29 </resource-ref>經過以上3個步驟,針對具體web項目配置的JNDI數據源就算是配置好了。具體的測試和上述測試全局JNDI數據源的方式是一樣的!
啦啦啦?
啦啦啦
轉載于:https://www.cnblogs.com/ClassNotFoundException/p/8334123.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的JNDI数据源的配置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python之面向对象四
- 下一篇: Java 接口 新特性(Java8)