1、JNDI(Java Naming and Directory Interface)Java命名和目錄接口:
| ●JNDI:是一個有關應用序設計的 API 為開發人員提供了查找和訪問各種命名和目錄服務的通用、 統一的接口; |
| ●JNDI的作用與優點: ★在應用與Java對象或資源之間建立松耦合的邏輯關聯,簡化應用對於資源的配置及維護工作; ★可以在更大范圍、不同應用之間共享資源; |
| ●JNDI 簡單地理解為是一種將對象和名字綁定的技術,即指定一個資源名稱,將該稱與某一資源或服務相關聯,當需要訪問其他組件和資源時,就需要使用 JNDI 服務進行定位. 應程序可以通過名字獲取對應的對象或服務; |
| ●JNDI 可以訪問的目錄及服務很多,eg:DNS、文件服務、數據庫等; |
| ●eg:在 Tomcat 中發布一條信息供所有的 Web 應用程序使用; 分析:Tomcat 根目錄\conf\context.xml 文件為全局的上下文配置文件,所有的 Web 應用有效。所將要發布的信息配置在此文件中,再通過 JNDI 來查找信息; 步驟1:在 Tomcat 中發布一條信息,修改context . xml 文件,代碼如下: <Context> <Environment name="tjndi" value="hello JNDI" type="java.lang.String" /> </Context> 注:< EnviTonment >元素用於配置命名的值, 所配置的值作為環境條目資源, 對整個 Web 應用可見。它包含的屬性:name、type、value; ◆name:環境條目的名稱,相對於 java:comp/env 的名稱; ◆type: 環境條目的 Java 類名的全稱; ◆value: 通過JNDI context 請求時,返回給應用的參數值,該值必須轉換成 type 屬性定義Java 類型; 步驟2:編寫 JSP 代碼 , 通過 JNDI 訪問環境條目,代碼如下: <body> <%@ page import="javax.naming.*" %> <% //javax.naming.Context提供了查找JNDI Resource的接口 Context ctx = new InitialContext(); //初始化Context對象 //java:comp/env/為前綴 String testjndi = (String) ctx.lookup("java:comp/env/tjndi"); //調用lookup()方法 out.print("test jndi:" + testjndi); %> </body> 注:◆java. naming包下的Context 接口表示命名上下文,它由一組名稱到對象的綁定組成。 ◆InitialContext是 Context接口的實現類; ◆Object lookup(String name) 方法根據名稱檢索指定對象, ◆為了避免 JNDI命名空間中的資源名稱互相沖突. 並且避免可移植性問題 Java EE 應用程序中的所有名稱應該以字串“java:comp/env”作為前綴;在上面的示例中:前綴后面的 'tjndi " 則對應着 context. xml 文件中< EnviTonment >元素的 name 屬性; |
| ●使用 JNDI 的步驟如下: (1)配置資源; (2) 通過 Context 的 lookup()方法查找資源; |
| ●使用application 應該也能滿足上述需求,但是 application 對象只能個 Web 應用程序中使用;使用 JNDI 發布的信息是對服務器上所有的 Web 應用程序都可見的,JNDI不只完成這種簡單的需求,它還提供了對其他資源的引用; |
2、 連接池(Connection Pool ):
| ●傳統數據庫連接技術: ◆傳統數據庫連接方式的不足: 1、需要經常與數據庫建立連接,在訪問結束后必須關閉連接釋放資源; 2、當並發訪問數量較大時,執行速度受到極大影響; 3、系統的安全性和穩定性相對較差; |
| ●數據庫連接池(Connection pooling)是程序啟動時建立足夠的數據庫連接,並將這些連接組成一個連接池,由程序動態地對池中的連接進行申請,使用,釋放。 ●數據庫連接池:數據庫連接池負責分配、管理和釋放數據庫連接; ★它允許應用程序重復使用一個現有的數據連接,而不再是重新建立一個; ★釋放那些空閑時間超過最大空閑時間的數據庫連接,以避免由於有釋放數據庫連接而引起的數據庫連接泄露; ★能明顯地提高對數據庫操作的性能; eg:日常生活中經常撥打熱線電話 (如 10086熱線電話對外是相同的號碼. 但是因為有多接線員 . 所以允許同時接A 多個電話。當然 ,如果所有的接線員都在工作,再有電話打入時就要進行等待,直到其中有接線員出現空閑; |
| ●數據庫連接池在初始化時將創建一定數量的數椐庫連並放到連接池中,這些數據庫連接的數量是由最小數據庫連接數來設定的。無論這些數據庫連接否被使用,連接池都將確保至少擁有這么多的連接數量。連接池的最大數據庫連接數量限定了這連接池能占有的最大連接數,當應用程序向連接池請求的連接數超過最大連接數量時,這些請求被加入等待隊列中; |
| ●連接池是如何管理連接的: 對於連接的管理可使用空閑池,即把巳經創建但尚未分配出去的連接存放到一個空閑池中;每當用戶請求一個連接時,系統首先檢查空閑池內有沒有空閑連接,如果有就分配一個連接給用戶;如果沒有則檢查當前連接池是否達到連接池所允許的最大連接數。如果沒有達到,就新建一個連接。如杲已經達到,就等待一定的間。如果在等待的時間內有連接被釋放出來,就可以把這個連接分配給等待的用戶;如果等待時間超過預定時間,則返回空值 (null),系統對已經分配出去正在使用的連接只做計數,當使用完后再返還給空閑池; |
3、數據源與連接池:
| ●數據源:數據源是在 JDBC 2. 0中引入的一個概念,在 JDBC 擴展包中定義了 javax.sql .DataSource 接口,它有一組特性用於確定和描述它所表示的現實存在的數據源,配置好的數據庫連接池也是DataSource 的形式存在,其實現類負責建立與數據庫的連接,在應用程序中訪問數據庫時不必編寫接數據庫的代碼,可以直接從數據源獲得數據庫連接; |
| ●javax.sql.DataSource接口的實現類: 1、負責管理與數據庫的連接; 2、以連接池的形式對數據庫連接進行管理; |
| ●在 DataSaice 中事先建立多個數據庫連接, 這些數據庫連接保存在座接池中。Java 程序訪問數鋸庫時只需從連接池中取出空閑狀態的數據庫連接,當程序訪問數據庫結束時,再將數據庫連接返回給接池. 這樣做可以提高訪問數據庫的效率. 以上過程如下圖: |
| 經驗:在傳統模式下,數據庫連接使用完畢后,需要將其關閉,釋放資源。而在連接池中,使用數據源獲得數據庫連接對象,在調用 close()方法時並不會真正地關閉連接,而僅僅實現了斷開應用程序與連接池之間的聯系,即將連接的使用權歸還給連接池; |
4、數據源與JNDI資源:
| ●如果將一個數據源實例發布在 Tomcat 環境中,那么Web 應用就可以通過 JNDI 進行訪問,通該數據源實例為 Web 應用提供數據庫連接的管理機制,從而簡化 Web 應用的數據庫連接管理問題; |
| ●DataSource 對象是由Web容器 (Tomcat ) 提供的,因此不能在程序中采用創建一個實例的方生成 DataSource對象,而需要通過 JNDI 來獲取: ★通過javax.naming.Context 的lookup()方法查找 JNDI Resource 的接口; eg:可以通過以下代碼獲得名稱為 jdbc/news 的數據源: //初始化上下文 Context ctx =new InitialContext(); //獲取與邏輯名相關聯的數據源對象 DataSource ds=(DateSources)ctx.lookup("java:comp/env/jdbc/news”); ★Tomcat把 DataSouce作為一種可配置的JNDI 資源來處理,假定配置了一個 DataSource , 數據源名稱為jdbc/news,應用程序訪問名為 jdbc/news的 DataSource 的過程如下: ★得到DateSource對象后,可以通過 DataSource 的getConnection ( ) 方法來獲得數據庫連接對象; Connection conn=ds.getConnection(); ★當程序結束數據庫訪問后,應該調用 Connection 的 close ( ) 方法及時將 Connection 返回給數據連接池 . 使 Comection 恢復空閑狀態; |
5、數據源的配置(下面以Tomcat為例講解如何配置數據源):
| ●使用連接池實現數據庫連接: 1、配置context.xml文件; 2、配置web.xml文件; 3、添加數據庫驅動文件; 4、進行代碼編寫,查找並使用lookup()方法獲取數據源對象; |
||||||||||||||||||||||
| ★Tomcat的conf/context.xml文件的配置: ◆上面JNDI時學習了如何在 context . xml 文件中增加<Environment>元素配置公共資源,而配數據源時需在<Context>節點下添加<Resource>元素; eg: <Context> <Resource name="jdbc/news" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="newsu" password="123456" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/newsmanagersystem? useUnicode=true&characterEncoding=utf-8" /> </Context> 注:對於url中出現的“&”,應將其替換為對應的實體“&” ▲Resource元素的屬性配置數據庫連接池的參數:
◆不同的Web 服務器,配置數據源的方式也是不一樣的,需要根據服務器提供的助文檔進行配置; |
||||||||||||||||||||||
| ★配置應用程序的web.xml文件:在web.xml中配置<resource-ref>: eg: <web-app> <resource-ref> <description>news DataSource</ description > <res-ref-name>jdbc/news</res-ref-name> // jdbc/news:指定JNDI的名字,與<Resource>元素中的name一致 <res-type>javax.sql.DataSource</res-type> // javax.sql.DataSource:指定引用資源的類名,與<Resource>元素中的type一致 <res-auth>Container</res-auth> // Container:指定管理所引用資源的Manager與<Resource>元素中的auth一致 </resource-ref> <!—省略其他配置信息--> < /web-app > ▲resource-ref元素的屬性:
◆<resource-ref>元素包含一個對外部資源的引用,它包含一個可選的description、一個引用資源的名稱(相對於java:comp/env環境的JDNI名)、資源類型、驗證方式; |
||||||||||||||||||||||
| ★添加數據庫驅動文件:把數據庫驅動jar文件,加入到Tomcat的lib中 |
||||||||||||||||||||||
| ★進行代碼編寫,查找並使用lookup()方法獲取數據源對象: importjavax.naming.Context; importjavax.naming.InitialContext; importjavax.naming.NamingException; importjavax.sql.DataSource; publicclass BaseDao { public Connection getConnection () { Connection conn = null; try { //獲取與邏輯名相關聯的數據源對象 Context ctx = new InitialContext(); DataSource ds=(DataSource)ctx.lookup("java:comp/env/jdbc/news"); conn = ds.getConnection(); } catch (SQLException exception) { exception.printStackTrace(); } catch (NamingException namingException) namingException.printStackTrace(); } return conn; } } |
||||||||||||||||||||||
| ●經驗:還有一種配置數據源方式,只需要在 WebRoot 目錄下的 META-NF 目錄中創建一個context.xml文件,添加<Context>節點,然后在<Context>節點中添加<Resource>元素內容; |
||||||||||||||||||||||
| ●數據源配置完畢,要通過數據源訪問數據庫,還要添加數據庫驅動文件. 由於數據源由 Tomcat創建並維護,所以必須把數據庫驅動文件放到 Tomcat 的 lib 目錄下; |
6、 常見錯誤:
| ●錯誤提示: Cannot load JDBC driVer class (不能加載驅動類); 錯誤原因及解決方案:通過數據源訪問數據庫,數據源由 Tomcat創建 , 應該把 JDBC 驅程序的 jar 文件復制到 Tomcat 的 jib 目錄下; |
| ●常見錯誤Cannot create JDBC driver of class ‘ ' for connect URL 'null' (由於連接路徑為null. 不能創建驅動 ); 錯誤原因及解決方案 : 此類錯誤多在數椐庫驅動或者在連接錯誤時出現,解決的方法是檢查 context . xml 文件中數據源配置的文件信息,確保配置信息完全正確; |
| ●錯誤信息:Name [news] is not bound in this Context (jdbc 名稱沒有綁定到當前上下文) 錯誤原因及解決方案 : ◆在使用lookup()方法查找數據源時,如果數據源名稱與配置中的名稱不一致,則程序運時會報此錯誤。解決方法是確保context. xml 文件中指定的數據源名稱與代碼中所要訪問數據源名稱一致; ◆在程序中調用 lookup()方法查找數據源時,沒有使用前綴 (java:comp/env/) +數據源名稱,則程序運行時會報此錯誤。解決方法是在使用 lookup()查找數據源時, 使用前綴(java:comp/env/) +數據源名稱的形式; |
7、 軟件分層模式:
| ●JSP開發時分兩層的弊端 |
| ●分層模式是最常見的一種架構模式;甚至可以說分層模是很多架構模式的基礎; ●分層模式是將解決方案的組件分隔到不同的層中,每一層中的組件應保內聚性,每一層都應與其下面的各層保持松耦合,對於一個小型系統一般三層就足夠了; |
| ●三層架構:三層指的是:表示層、業務邏輯層、數據訪問層; ◆表示層:位於最外層 ( 最上層 ),使用戶能夠直接訪問,用於顯示數據和接收用戶輸入的數據,為用戶提供一種交互式操作界面。在 Web 應用程序中,表示層一般以 JSP 文件、HTML文件為主; ◆業務邏輯層:其主要功能是提供對業務邏輯處理的封裝,在業務邏輯層中,通常會定義些接口,表示層通過調用業務邏輯層的接口實現各種操作,如數據有效性的檢驗. 業務輯描述等相關功能,業務邏輯層經常放在 service 包或 biz 包下,btz 是英文 buslness 的縮寫,意思是 '業務邏輯"; ◆數據訪問層:該層實現對數據的保存和讀取操作。數據訪問,可以訪問關系數椐庫、文件或 XML 文檔等。數據訪問層通常放在 dao 包下,DAO 是英文 Data Access Object 的縮寫,意思是 "數據訪問對象 "; |
| ●層與層之間的關系: ◆在三層架構中各層之間相互依賴。表示層依賴於業務邏輯層,業務邏輯層依賴於數據訪層,各層之間的數據傳遞方向分為請求與晌應兩個方向; ★如圖: ◆表示層根據用戶的操作,將請求提交給業務邏輯層 ;業務輯層收到請求,首先對請求數據進行必要的審核和處理,然后請求通知數據訪問層或直接將處理結果返回表示層,數據訪問層收到業務邏輯層的調用后便開始訪問數據庫; ◆業務邏輯層在體系架構中的位置非常關鍵,起到數據交換承上啟下的作用。理想的分層式架構. 應該是一個支持可抽取可替換的 “抽屜” 式架構。 業務邏輯層的設計對於一個支持可展的架構尤為關鍵,因為它扮演了兩個不同的角色。對於數據訪問層而言,他是調用者,對於表示層而言,它卻是被調用者。 ◆數據訪問層通過對數據庫的訪問得到請求結果,並把請求結果通知業務邏輯層;業務邏輯層到請求結果,可以對請求結果進行必要的審核和處理,然后將請求結果通知表示層;表示層收到求結果,並把結果展示給用戶。 |
| ●分層原則: 1、上一層依賴其下一層、依賴關系不跨層: ★上一層調用下一層所得到的執行結果完全取決於下一層中的代碼實現,上一層無法進行控; 2.下一層不能調用上一層: ★上一層調用下一層功能,下一層不能調用上一層功能。下一層為上一層提供服務,而不使用上一層提供的服務; 3.下一層不依賴上一層: ★下一層的代碼實現決定了上一層獲得的內容,所以說上一層依賴下一層,從另一個角度來說,上一層不管如何發生改變. 對於其調用下一層的業務是不會發生變化的,因此對於下一層來說,上一層的改變不會對其產生任何影響; 4.在上一層中不能出現下一層的概念: ★使用分層架構的一個優點是在系統中各個功能分工明確,在某一層中不會出現其下一層的任內容,簡單地說就是在業務邏輯層中. 只能有用於業務邏輯控制的代碼,而不能出現數據庫訪問層中才有的 SQL 語句 , 確保層次間的關系很清晰; |
8、使用三層架構開發的特點和優勢:
| ●使用三層開發的特點: ★下層不知上層的存在; ★每一層僅知它下一層的存在,而不知另外的下層; ★上層使用下層提供的服務,並為下層提供數據; |
| ●分層思想:就是指這樣一種分工,它將系統按不同職責組織成有序的層次。其中,除最上層外,每一層僅提供若干服務供其相鄰的上層使用,但不上層的存在;除了最下層外,每一層僅調用其臨近下層的服務; |
| ●分層的優點: ★職責划分清晰; ◆由於某一層僅僅調用其相鄰下一層所提供的服務, 所以,只要本層的實現和相鄰下一層的實現定義完整,開發人員在開發某一層時就可以將關注集中於這一層所用的思想、模式、技術,而無需關心其他層的具體實現; ★利用面向對象的特性迸行無損替換; ★復用代碼; ◆例如:鐵路局制作發布了一個 “ Business Service' , 用於提供火車車次預告信息,這樣火車票代售網站就可以利用這個服務層提供的服務制作火車票信息頁面,而無須再重新實現獲取信息的功能; ★降低了系統內部的依賴程度: ◆例如:在三層架構中,表示層只與業務邏輯層聯系,而對業務邏輯層下還有哪些層並不關心,表示層只依賴於業務邏輯; |
| ●分層的弊端: ★例如,原本很直接的操作,現在要通過層層傳遞,勢必造成性能的下降; ★另外,雖然分層架構可以降低層內變化的成本,但對於功能定義 (接口定義)變化非常敏感;功能定義的變動對於分層架構是致命的,修改起來難度非常大。所以,一個簡單的判斷法則是,如果系統層內實現頻繁變動 (甚至整層替換) 的可能性很大,而功能定義變動的可性很小,就使用分層; |
9、附加:
| ●JSP三層架構:當不采用分層式結構,很多業務可以直接造訪數據庫,以此獲取相應的數據,現在通過中間層來完成影響系統性能; ●使用三層架構,分別是表示層、業務邏輯層、數據訪問層,各層之間分工明細,職責划分非常的清晰,而且代碼的重用性也提高了很多,同事也降低了系統內部的依賴程度,實現無損替換,構建松耦合架構。 |
| ●三層開發的優勢包括松耦合、重用性高、生命周期成本低、可維護性高。 ●三層分別為:表現層(UI)、業務邏輯層(BLL)、數據訪問層(DAL)。 作用: 1.解耦。 2.簡化復雜問題。 3.便於系統維護/升級。 4.邏輯復用。 5.便於團隊開發。 6.方便部署。 |
| ●業務邏輯層訪問數據訪問層,數據訪問層執行對數據庫的訪問,並將請求結果通知業務邏輯層,業務邏輯層再將結果通知表示層,注意:業務邏輯層不直接對數據庫訪問。上一層依賴其下一層、依賴關系不跨層; |
| ●MVC是由三部分組成: 表示層、視圖層(VIEW)JSP,主要做頁面的顯示效果,用於顯示以及獲取界面的數據; 控制層(控制器)(Controller)Servlet,主要做接受請求和響應的、控制頁面跳轉等; 模型層(Model)JavaBean:主要做業務處理,處理上層傳遞來的數據以及從數據庫獲取的數據的; |
| ●MVC是復合模式,結合了觀察者模式、策略模式和組合模式。模型使用Observer,控制器是視圖的策略,視圖使用組合模式實現用戶界面。適配器是使用MVC時,經常附帶用到的技巧:使用適配器將模型適配成符合現有視圖和控制器的需要的模型。 ●MVC 和Model2的區別:Model 2架構中呈現視圖的技術並沒有限制 |
| MVC架構也可以應用於3-tier的網絡架構中,其中模型通知視圖時,可以透過Socket聯機來進行。 |
| ●maxWait: 最大等待秒數, 單位為 ms, 超過時間會丟出錯誤信息,-1為無限制; |
| 數據庫連接池技術:
|
| ●動態include用jsp:include動作實現 <jsp:include page=included.jsp flush=true />它總是會檢查所含文件中的變化,適合用於包含動態頁面,並且可以帶參數; 靜態include用include偽碼實現,不會檢查所含文件的變化,適用於包含靜態頁面 <%@ include file=included.html %> |
| ●Name jdbc is not bound in this Context。這種錯誤是因為根據JNDI名稱查找數據源的時候出現錯誤,可能的錯誤原因如下: |
| ●由於數據源由Tomcat 維護,所以在程序中要獲取DataSource對象,需要通過JNDI來獲取數據源,不能采用創建一個實例的方式來生成。 |









