Java使用JNDI連接數(shù)據(jù)庫的實現(xiàn)方法
項目背景
在項目中本身使用的SQL Server 數(shù)據(jù)庫,某些功能下需要訪問Sybase數(shù)據(jù)庫(都淘汰的東西 QAQ),考慮到功能較少并且我們的UAT和PROD環(huán)境使用的是WebSphere,其本身已經(jīng)存在JNDI的連接方式,因此我決定使用JNDI設(shè)置,那么就需要解決JNDI在Tomcat下的配置了,找了很多資料,說到這,不得不吐槽我們國內(nèi)的博客論壇,大部分都是抄,關(guān)鍵是還抄不全,錯漏百出,還不注明原作者。
環(huán)境
Eclipse:Luna
Tomcat:apache-tomcat-9.0.8
概念
數(shù)據(jù)源與連接池
數(shù)據(jù)源名稱(data source name,DSN)是包含了有關(guān)某個特定數(shù)據(jù)庫信息的數(shù)據(jù)結(jié)構(gòu),這個信息是開放式數(shù)據(jù)庫連接驅(qū)動能夠連接到數(shù)據(jù)庫上必需的信息,其實本質(zhì)上就使程序與數(shù)據(jù)庫連接的通道。數(shù)據(jù)源中并無真正的數(shù)據(jù),它僅僅記錄的是你連接到哪個數(shù)據(jù)庫,以及如何連接的,如odbc數(shù)據(jù)源。也就是說數(shù)據(jù)源僅僅是數(shù)據(jù)庫的連接名稱,一個數(shù)據(jù)庫可以有多個數(shù)據(jù)源連接。
在Java語言中,DataSource對象就是一個代表數(shù)據(jù)源實體的對象。一個數(shù)據(jù)源就是一個用來存儲數(shù)據(jù)的工具,它可以是復(fù)雜的大型企業(yè)級數(shù)據(jù)庫,也可以是簡單得只有行和列的文件。數(shù)據(jù)源可以位于在服務(wù)器端,也可以位于客服端。
連接池:在Java程序中,當(dāng)我們需要對數(shù)據(jù)庫進(jìn)行操作時,對于數(shù)據(jù)庫的增刪改查等操作的前提是需要與數(shù)據(jù)庫建立連接,而對于連接的管理其實就使建立在數(shù)據(jù)源的基礎(chǔ)上,即連接池。
常用的數(shù)據(jù)庫連接池:
序號 | 連接池名稱 | 依賴的jar包 | 實現(xiàn)的datasource類 | 備注 |
---|---|---|---|---|
1 | JNDI | 該數(shù)據(jù)源是由相應(yīng)的web服務(wù)器(例如:tomcat,weblogic,websphere)負(fù)責(zé)初始化,創(chuàng)建,管理。程序中不需要引入特別的jar包。 | Javax.sql.datasource | |
2 | C3P0 | c3p0-0.9.xxx.jar | com.mchange.v2.c3p0.ComboPooledDataSource | |
3 | DBCP | commons-dbcp.jar commons-pool.jar |
org.apache.commons.dbcp.BasicDataSource | |
4 | BoneCP | bonecp-0.6.5.jar google-collections-1.0.jar slf4j-api-1.5.11.jar,slf4j-log4j12-1.5.11.jar log4j-1.2.15.jar |
BoneCPDataSource |
什么是JNDI
jndi全稱是java naming and directory interface。簡單點就是你按命名規(guī)則給一個東西命名然后你就可以通過該名字在特定環(huán)境下直接查找到該東西了。
JNDI是用于向Java程序提供目錄和命名功能的API。可以簡單地把JNDI理解為一種將對象和名字綁定的技術(shù),對象工廠負(fù)責(zé)生產(chǎn)出對象,這些對象都和惟一的名字綁定。外部程序可以通過名字來獲取對某個對象的引用。在一個文件系統(tǒng)中,文件名被綁定給文件。在DNS中,一個IP地址綁定一個URL。在目錄服務(wù)中,一個對象名被綁定給一個對象實體。
在Intranets(企業(yè)內(nèi)部網(wǎng))和Internates(互聯(lián)網(wǎng))中目錄服務(wù)(Directory service)都非常重要,它規(guī)范了命名規(guī)則,讓人們?nèi)菀桌斫鈱嶓w及之間的關(guān)系。JNDI是Java平臺的一個標(biāo)準(zhǔn)擴(kuò)展,提供了一組接口、類和關(guān)于命名空間的概念。JNDI目前所支持的技術(shù)包括LDAP、CORBA Common Object Service(COS)名字服務(wù)、RMI、NDS、DNS、Windows注冊表等等。
jndi被設(shè)計成獨立于特定的目錄服務(wù),所以各種各樣的目錄都可以通過相同的方式進(jìn)行訪問。這樣使用jndi的java程序員不僅可以獲得統(tǒng)一規(guī)整的命名和目錄,而且可以通過多層的命名方案無縫訪問(seamless acess)目錄對象。
JNDI優(yōu)點
JNDI是由web服務(wù)器,實現(xiàn)了java.sql.datasource。由web服務(wù)器負(fù)責(zé)初始化數(shù)據(jù)源,創(chuàng)建connection,分配,管理connection。由于本身是由web服務(wù)器實現(xiàn)的功能,因此不需要在項目project中引入特別的jar包,但是需要在服務(wù)器的某些配置文件中增加相關(guān)的配置。對于我們這種連接多個數(shù)據(jù)庫有很好的效果。
JDNI在Tomcat中的配置
Jar包
1.數(shù)據(jù)庫的驅(qū)動程序包:
jconn4.jar Sybase驅(qū)動程序包
mssql-jdbc-6.1.0.jre7.jar SQL Server 程序驅(qū)動包
2.JSP標(biāo)簽Ja包
.jstl-1.2.jar
standard-1.1.2.jar
測試準(zhǔn)備
新建測試Web項目如下:
JSP:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ page import="java.sql.*,javax.sql.*,javax.naming.*" %> <!DOCTYPE HTML> <html> <head> <title>JNDI數(shù)據(jù)源測試</title> </head> <body> <% Connection connOracle = null; try { //1、初始化名稱查找上下文 Context ctx = new InitialContext(); //InitialContext ctx = new InitialContext();亦可 //2、通過JNDI名稱找到DataSource,對名稱進(jìn)行定位java:comp/env是必須加的,后面跟的是DataSource名 /* DataSource名在web.xml文件中的<res-ref-name>oracleDataSource</res-ref-name>進(jìn)行了配置 <!--Oracle數(shù)據(jù)庫JNDI數(shù)據(jù)源引用 --> <resource-ref> <description>Oracle DB Connection</description> <res-ref-name>oracleDataSource</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> */ DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/Sybase_claims"); //3、通過DataSource取得一個連接 connOracle = ds.getConnection(); out.println("Sybase Connection pool connected !!"); //4、操作數(shù)據(jù)庫 } catch (NamingException e) { System.out.println(e.getMessage()); } catch (SQLException e) { e.printStackTrace(); } finally { //5、關(guān)閉數(shù)據(jù)庫,關(guān)閉的時候是將連接放回到連接池之中 connOracle.close(); } %> <hr/> <% Connection connSQLServer = null; try { //1、初始化名稱查找上下文 Context ctx = new InitialContext(); //InitialContext ctx = new InitialContext();亦可 //2、通過JNDI名稱找到DataSource,對名稱進(jìn)行定位java:comp/env是必須加的,后面的是DataSource名 /* DataSource名在web.xml文件中的<res-ref-name>sqlserverDataSource</res-ref-name>進(jìn)行了配置 <!--SQLServer數(shù)據(jù)庫JNDI數(shù)據(jù)源引用 --> <resource-ref> <description>SQLServer DB Connection</description> <res-ref-name>sqlserverDataSource</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> */ DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/sqlserver"); //3、通過DataSource取得一個連接 connSQLServer = ds.getConnection(); out.println("SQLServer Connection pool connected !!"); //4、操作數(shù)據(jù)庫 } catch (NamingException e) { System.out.println(e.getMessage()); } catch (SQLException e) { e.printStackTrace(); } finally { //5、關(guān)閉數(shù)據(jù)庫,關(guān)閉的時候是將連接放回到連接池之中 connSQLServer.close(); } %> </body> </html>
Tomcat:
將數(shù)據(jù)庫驅(qū)動Jar包放入Tomcat的lib文件夾下:
JNDI配置
在Tomcat 配置文件server.xml(apache-tomcat-9.0.8\conf)中的GlobalNamingResources標(biāo)簽內(nèi)定義
<!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html --> <GlobalNamingResources> <!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users --> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> <!-- |- name:表示以后要查找的名稱。通過此名稱可以找到DataSource,此名稱任意更換,但是程序中最終要查找的就是此名稱, 為了不與其他的名稱混淆,所以使用jdbc/oracle,現(xiàn)在配置的是一個jdbc的關(guān)于oracle的命名服務(wù)。 |- auth:由容器進(jìn)行授權(quán)及管理,指的用戶名和密碼是否可以在容器上生效 |- type:此名稱所代表的類型,現(xiàn)在為javax.sql.DataSource |- maxActive:表示一個數(shù)據(jù)庫在此服務(wù)器上所能打開的最大連接數(shù) |- maxIdle:表示一個數(shù)據(jù)庫在此服務(wù)器上維持的最小連接數(shù) |- maxWait:最大等待時間。10000毫秒 |- username:數(shù)據(jù)庫連接的用戶名 |- password:數(shù)據(jù)庫連接的密碼 |- driverClassName:數(shù)據(jù)庫連接的驅(qū)動程序 |- url:數(shù)據(jù)庫連接的地址 --> <!--配置Sysbase數(shù)據(jù)庫的JNDI數(shù)據(jù)源--> <Resource name="jdbc/Sybase_claims" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="test" password="test" driverClassName="com.sybase.jdbc4.jdbc.SybDriver" url="jdbc:sybase:Tds:127.0.0.1:4101?ServiceName=db_claims"/> <!--配置SQL Server數(shù)據(jù)庫的JNDI數(shù)據(jù)源--> <Resource name="jdbc/sqlserver" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="sa" password="p@ssw0rd" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" url="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=sonora"/>
全局引用
在Tomcat 的context.xml(apache-tomcat-9.0.8\conf)中引用,針對于本Tomcat服務(wù)器下所有項目使用。
<Context> <!-- Default set of monitored resources. If one of these changes, the --> <!-- web application will be reloaded. --> <WatchedResource>WEB-INF/web.xml</WatchedResource> <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> <!-- Uncomment this to disable session persistence across Tomcat restarts --> <!-- <Manager pathname="" /> --> <ResourceLink name="jdbc/Sybase_claims" global="jdbc/Sybase_claims" type="javax.sql.DataSource"/> <ResourceLink name="jdbc/Sybase_iws_ref" global="jdbc/Sybase_iws_ref" type="javax.sql.DataSource"/> </Context>
當(dāng)然,我們也可以不引用局部配置的,在Context標(biāo)簽中直接寫數(shù)據(jù)源:
<Context> <!-- Default set of monitored resources. If one of these changes, the --> <!-- web application will be reloaded. --> <WatchedResource>WEB-INF/web.xml</WatchedResource> <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> <!-- Uncomment this to disable session persistence across Tomcat restarts --> <!-- <Manager pathname="" /> --> <!--配置Sysbase數(shù)據(jù)庫的JNDI數(shù)據(jù)源--> <Resource name="jdbc/Sybase_claims" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="test" password="test" driverClassName="com.sybase.jdbc4.jdbc.SybDriver" url="jdbc:sybase:Tds:127.0.0.1:4101?ServiceName=db_claims"/> <!--配置SQL Server數(shù)據(jù)庫的JNDI數(shù)據(jù)源--> <Resource name="jdbc/sqlserver" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="sa" password="p@ssw0rd" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" url="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=sonora"/> </Context>
局部引用
局部引用:即是配置的數(shù)據(jù)源,只針對于指定項目使用。
方式一:在server.xml中的host標(biāo)簽內(nèi)配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> <Context docBase="jndi_demo" path="/jndi_demo" reloadable="false"> <ResourceLink name="jdbc/Sybase_claims" global="jdbc/Sybase_claims" type="javax.sql.DataSource"/> <ResourceLink name="jdbc/sqlserver" global="jdbc/sqlserver" type="javax.sql.DataSource"/> </Context> </Host>
當(dāng)然也也可以直接在Context標(biāo)簽下直接定義
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> <Context docBase="jndi_demo" path="/jndi_demo" reloadable="false"> <Resource name="jdbc/Sybase_claims" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="test" password="test" driverClassName="com.sybase.jdbc4.jdbc.SybDriver" url="jdbc:sybase:Tds:127.0.0.1:4101?ServiceName=db_claims"/> <!--配置SQL Server數(shù)據(jù)庫的JNDI數(shù)據(jù)源--> <Resource name="jdbc/sqlserver" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="sa" password="p@ssw0rd" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" url="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=sonora"/> </Context> </Host>
方式二:在Tomcat安裝目錄下apache-tomcat-9.0.8\conf\Catalina\localhost下新建xml文件,文件名與項目名稱相同。
<!--映射JNDITest項目的虛擬目錄--> <Context docBase="D:/soft-install/apache-tomcat-9.0.8/webapps/jndi_demo/WebContent" debug="0" reloadable="false"> <!--引用Sybase數(shù)據(jù)庫的JNDI數(shù)據(jù)源--> <ResourceLink name="jdbc/Sybase_claims" global="jdbc/Sybase_claims" type="javax.sql.DataSource"/> <!--引用sqlserver數(shù)據(jù)庫的JNDI數(shù)據(jù)源--> <ResourceLink name="jdbc/sqlserver" global="jdbc/sqlserver" type="javax.sql.DataSource"/> </Context>
方式三:
在Tomcat下項目目錄的META-INF中新建Context.xml 配置JNDI引用,例如:、apache-tomcat-9.0.8\webapps\jndi_demo\META-INF、。
<Context reloadable="false"> <ResourceLink name="jdbc/Sybase_claims" global="jdbc/Sybase_claims" type="javax.sql.DataSource"/> <ResourceLink name="jdbc/sqlserver" global="jdbc/Sybase_iws_ref" type="javax.sql.DataSource"/> </Context>
或
<?xml version="1.0" encoding="UTF-8"?> <Context path="" reloadable="false"> <Resource name="jdbc/Sybase_claims" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="test" password="test" driverClassName="com.sybase.jdbc4.jdbc.SybDriver" url="jdbc:sybase:Tds:127.0.0.1:4101?ServiceName=db_claims"/> <!--配置SQL Server數(shù)據(jù)庫的JNDI數(shù)據(jù)源--> <Resource name="jdbc/sqlserver" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="sa" password="p@ssw0rd" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" url="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=sonora"/> </Context>
這樣做的好處就是可以脫離Tomcat配置的更改。
注意
1.看了很多文章,有些是在項目web.xml中配置如下內(nèi)容,經(jīng)過的驗證Tomcat中是可有可無的,不過有些文章說最好加上,以便于項目移植,因為有些服務(wù)器是需要的。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- JNDI配置的資源引用: ? res-ref-name:表示引用資源的名稱 ? res-type:此資源對應(yīng)的類型為javax.sql.DataSource ? res-auth:容器授權(quán)管理 --> <!--Sybase數(shù)據(jù)庫JNDI數(shù)據(jù)源引用 --> <resource-ref> <description>Sybase DB Connection</description> <res-ref-name>jdbc/Sybase_claims</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> <!--SQLServer數(shù)據(jù)庫JNDI數(shù)據(jù)源引用 --> <resource-ref> <description>SQLServer DB Connection</description> <res-ref-name>jdbc/sqlserver</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app>
JNDI配置我們可以發(fā)現(xiàn),第三種方式完全脫離Tomcat的配置,對于server的影響較小。不過我比較推薦全局配置,各處引用,方便切換。
Tomcat的配置修改后,最好重啟Tomcat以便生效,對于server.xml修改必須重啟生效,而context.xml配置保存后tomcat會自動加載無需重啟
JNDI數(shù)據(jù)源獲取寫法有一下兩種,前者是針對于Tomcat中的,而后者是針對于IBM WebSphere。
A: java:comp/env/jdbc/Sybase_claims
B: jdbc/Sybase_claims
針對于A:
java:comp/env 是環(huán)境命名上下文(environment naming context(ENC)),是在EJB規(guī)范1.1以后引入的,引入這個是為了解決原來JNDI查找所引起的沖突問題,也是為了提高EJB或者J2EE應(yīng)用的移植性。
在J2EE中的引用常用的有:
JDBC 數(shù)據(jù)源引用在java:comp/env/jdbc 子上下文中聲明
JMS 連接工廠在java:comp/env/jms 子上下文中聲明
JavaMail 連接工廠在java:comp/env/mail 子上下文中聲明
URL 連接工廠在 java:comp/env/url子上下文中聲明
參考資料
https://www.cnblogs.com/wuyanshun/p/6763162.html
http://tomcat.apache.org/tomcat-9.0-doc/jndi-resources-howto.html
到此這篇關(guān)于Java使用JNDI連接數(shù)據(jù)庫的實現(xiàn)方法的文章就介紹到這了,更多相關(guān)Java JNDI連接數(shù)據(jù)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java連接MySQL數(shù)據(jù)庫實例
- Java使用JDBC連接數(shù)據(jù)庫的詳細(xì)步驟
- 詳解Java使用JDBC連接MySQL數(shù)據(jù)庫
- Java使用JDBC連接數(shù)據(jù)庫
- Java連接MySQL數(shù)據(jù)庫命令行程序過程
- 詳細(xì)說明關(guān)于Java的數(shù)據(jù)庫連接(JDBC)
- 一篇文章帶你了解java數(shù)據(jù)庫連接
- 詳解Java數(shù)據(jù)庫連接池
- Java基礎(chǔ)之JDBC的數(shù)據(jù)庫連接與基本操作
- Java 數(shù)據(jù)庫連接(JDBC)的相關(guān)總結(jié)
- Java 如何使用JDBC連接數(shù)據(jù)庫
- Java連接數(shù)據(jù)庫的步驟介紹
相關(guān)文章
Java異常處理中同時有finally和return語句的執(zhí)行問題
這篇文章主要介紹了Java異常處理中同時有finally和return語句的執(zhí)行問題,首先確定的是一般finally語句都會被執(zhí)行...然后,需要的朋友可以參考下2015-11-1125行Java代碼將普通圖片轉(zhuǎn)換為字符畫圖片和文本的實現(xiàn)
這篇文章主要介紹了25行Java代碼將普通圖片轉(zhuǎn)換為字符畫圖片和文本的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04