明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

Servlets與JSP Pages最佳實(shí)戰(zhàn)

[摘要]Java Servlet技術(shù)與JSP技術(shù)使Java服務(wù)器端技術(shù),目前他們控制了整個(gè)服務(wù)器端Java技術(shù)市場(chǎng),并且逐漸成為構(gòu)建商業(yè)Web應(yīng)用的標(biāo)準(zhǔn)。Java開發(fā)者喜歡這些技術(shù)是由于很多的原因,包括:這些技術(shù)很容易學(xué)習(xí),一次編寫,處處運(yùn)行(Write Once, Run Anywhere)。更重要的是...

Java Servlet技術(shù)與JSP技術(shù)使Java服務(wù)器端技術(shù),目前他們控制了整個(gè)服務(wù)器端Java技術(shù)市場(chǎng),并且逐漸成為構(gòu)建商業(yè)Web應(yīng)用的標(biāo)準(zhǔn)。Java開發(fā)者喜歡這些技術(shù)是由于很多的原因,包括:這些技術(shù)很容易學(xué)習(xí),一次編寫,處處運(yùn)行(Write Once, Run Anywhere)。更重要的是,如果更高效地采用了下面的實(shí)踐,Servlet與JSP能夠幫助分開Web的表示與內(nèi)容!白罴褜(shí)踐”是被證明為開發(fā)高質(zhì)量、可重用與易維護(hù)的基于Servlet和JSP的Web應(yīng)用的較好方法。與此相對(duì)應(yīng)的是,將Java代碼混合在HTML中,這樣很容易產(chǎn)生低效率、不易重用、難于維護(hù)的復(fù)雜應(yīng)用程序。最佳實(shí)踐將改變這些弊端。

本文將描述為Servlets與JSP準(zhǔn)備的最佳實(shí)踐的重要性;這里假設(shè)讀者已經(jīng)了解兩者的基本工作原理。這篇文章將涵蓋以下內(nèi)容:

  • 簡(jiǎn)要介紹Java Servlet與JavaServer Pages (JSP)。
  • 為開發(fā)Servlets 與JSP提供一些提示,技巧與規(guī)則。
  • 為Servlet與JSP提供最佳實(shí)踐。

Servlet和JSP Pages概述

類似于通用網(wǎng)關(guān)接口(CGI)腳本,servlets支持請(qǐng)求響應(yīng)編程模式。當(dāng)客戶端給服務(wù)器發(fā)送請(qǐng)求時(shí),服務(wù)器將請(qǐng)求發(fā)送給servlet。然后,servlet構(gòu)建一個(gè)響應(yīng),服務(wù)器將該響應(yīng)發(fā)送回客戶端。然而,跟CGI腳本不同的是,servlets和HTTP服務(wù)器運(yùn)行在同一個(gè)進(jìn)程內(nèi)。

當(dāng)發(fā)出客戶端請(qǐng)求的時(shí)候,調(diào)用service 方法并傳遞一個(gè)請(qǐng)求和響應(yīng)對(duì)象。Servlet首先判斷該請(qǐng)求是GET 操作還是POST 操作。然后它調(diào)用下面的一個(gè)方法:doGet 或 doPost。如果請(qǐng)求是GET就調(diào)用doGet方法,如果請(qǐng)求是POST就調(diào)用doPost方法。doGet和doPost都接受請(qǐng)求(HttpServletRequest)和響應(yīng)(HttpServletResponse)。

最簡(jiǎn)單地說,servlets是能夠使用print語句產(chǎn)生動(dòng)態(tài)HTML內(nèi)容的Java類。然而,有一點(diǎn)必須要提一下,那就是servlets是在一個(gè)容器內(nèi)運(yùn)行的,并且APIs 提供了對(duì)會(huì)話和對(duì)象的生命周期的管理。因此,當(dāng)你使用servlets時(shí),你就能獲得Java平臺(tái)的所有優(yōu)勢(shì),它包括沙箱 (安全)、通過JDBC的數(shù)據(jù)庫存取API和具有跨平臺(tái)可移植性的servlets。

Java Server Pages (JSP)

JSP技術(shù)是Servlet技術(shù)的一個(gè)較高層次的抽象。它是Sun公司開發(fā)、開放的技術(shù),是與Microsoft公司的ASP動(dòng)態(tài)網(wǎng)頁技術(shù)相似的一種技術(shù),并且它是Java2 企業(yè)版(J2EE)的一個(gè)關(guān)鍵組件。目前,很多商業(yè)的應(yīng)用服務(wù)器(例如BEA WebLogic, IBM WebSphere, Live JRun, Orion等等)都支持JSP。
 

JSP頁面如何工作?

JSP頁面實(shí)際上是一個(gè)帶有傳統(tǒng)HTML和Java代碼的Web頁面。JSP頁面的文件擴(kuò)展名是.jsp而并不是.html或.htm,該擴(kuò)展名告訴服務(wù)器該頁面需要特殊的處理,該特殊處理必須由服務(wù)器擴(kuò)展或插件實(shí)現(xiàn)。

當(dāng)一個(gè)JSP頁面被讀取時(shí),他首先將被編譯(JSP引擎來做這件事情)為一個(gè)Servlet。 這時(shí)候這個(gè)Servlet就像其他Servlet一樣被交給Servlet引擎來處理。然后Servlet引擎讀取那個(gè)Servlet對(duì)應(yīng)的類(用ClassLoader)并且執(zhí)行它,產(chǎn)生一個(gè)動(dòng)態(tài)HTML頁面(圖1)。這個(gè)Servlet創(chuàng)建一些必需的元件,然后將這些元件作為一個(gè)字符串寫入輸出流(OutputStream),并顯示在瀏覽器中。
調(diào)用JSP頁面時(shí),首先會(huì)將它編譯成一個(gè) (通過JSP引擎) Java servlet。這時(shí),servlet引擎處理該servlet,就像處理任何其他servlet一樣。然后,servlet引擎加載servlet類 (使用類加載器) 并執(zhí)行它創(chuàng)建動(dòng)態(tài)HTML發(fā)送給瀏覽器,如圖1所示。Servlet創(chuàng)建所有必需的對(duì)象,并將所有對(duì)象作為字符串寫入到輸出流中,并在瀏覽器中顯示。


1: 調(diào)用一個(gè)JSP頁面的請(qǐng)求/響應(yīng)流程圖

下次請(qǐng)求該頁面的時(shí)候,JSP引擎執(zhí)行早就裝載的servlet除非JSP頁面早就更改,在這種情況下,會(huì)將它自動(dòng)重新編譯進(jìn)一個(gè)servlet中并執(zhí)行。

最佳實(shí)踐

在本節(jié)中,將描述在Servelt, 特別是JSP中的最佳實(shí)踐。強(qiáng)調(diào)JSP最佳實(shí)踐是因?yàn)镴SP比Servlet得到更為廣泛的應(yīng)用(也許是因?yàn)镴SP技術(shù)促進(jìn)了表示與邏輯的分離)。一個(gè)集成Servlet與JSP的最佳實(shí)踐是“模型-顯示-控制器”設(shè)計(jì)模式(Model View Controller, MVC),將在本文的后面部分進(jìn)行討論。

  • HTML頁面中不要過多使用Java代碼: 將所有的Java代碼直接放在JSP頁面中,對(duì)于小項(xiàng)目而言沒有問題,但是過度使用將會(huì)導(dǎo)致意大利面條似的代碼,難于閱讀,難于理解。減少Java代碼的方法是編寫?yīng)毩⒌腏ava類來實(shí)現(xiàn)計(jì)算等邏輯。一旦測(cè)試了這些類,就創(chuàng)建了實(shí)例。
  • 選擇合適的include機(jī)制: 最好將頁眉、頁腳和導(dǎo)航條內(nèi)容存儲(chǔ)在單個(gè)文件中,并且不要重新動(dòng)態(tài)產(chǎn)生它們。一旦將這些內(nèi)容存儲(chǔ)在各個(gè)獨(dú)立的文件中,使用下面include機(jī)制中的任何一個(gè)就能在所有的頁面中引入它們:
    1. Include 指令: <%@ include file="filename" %>
    2. Include行為: <jsp:include page="page.jsp" flush="true" />


當(dāng)JSP正在轉(zhuǎn)換成Servlet時(shí),第一種include機(jī)制將包含指定文件的內(nèi)容(轉(zhuǎn)換階段),對(duì)于第二種include機(jī)制來說,當(dāng)該頁面執(zhí)行后時(shí),頁面包含了用Response產(chǎn)生的內(nèi)容。當(dāng)被包含的頁面不太改變的時(shí)候,我推薦使用第一種include指令方式,這種方式比較快,性能較好;當(dāng)被包含的文件經(jīng)常改變(其中也有動(dòng)態(tài)內(nèi)容)時(shí),并且在執(zhí)行主頁的時(shí)候不能確定所要引入的的頁面的時(shí)候,使用第二種include行為方式。

另一種include機(jī)制是使用JSP標(biāo)準(zhǔn)標(biāo)記庫(JSTL)中的<c:import> 行為標(biāo)記。可以使用這種方式來包含本地的或者遠(yuǎn)程的文件,下面是一些例子:

<c:import url="./copyright.html"/>
<c:import url="http://www.somewhere.com/hello.xml"/>
  • 不要將業(yè)務(wù)邏輯和表示混合起來: 在更為復(fù)雜的應(yīng)用中,并且更多的代碼被引入時(shí),很重要的一點(diǎn)是不要將業(yè)務(wù)邏輯與表示混在同一個(gè)文件中。分開業(yè)務(wù)邏輯與表示使得當(dāng)其中的任何一方需要改動(dòng)是不至于影響到另外一方。JSP僅僅被作為前臺(tái)的表示。那么,該如何實(shí)現(xiàn)業(yè)務(wù)邏輯部分呢?這就是JavaBeans的用武之地了。JavaBeans技術(shù)是輕便的、平臺(tái)無關(guān)的組建模型,它使開發(fā)人員編寫組件并且可以處處運(yùn)行。在JSP環(huán)境中,JavaBeans組件處理業(yè)務(wù)邏輯并返回?cái)?shù)據(jù)給JSP頁面,這反過來格式化從JavaBeans組件返回的數(shù)據(jù),以便在瀏覽器中顯示。JSP頁面通過調(diào)用JavaBeans組件的get方法和set方法來操作Bean的各項(xiàng)屬性。使用JavaBeans技術(shù)的好處如下:
    1. 可重用:不同的應(yīng)用可以使用同一個(gè)組件。 
    2. 分離業(yè)務(wù)邏輯與表示:可以在JSP頁面上改變數(shù)據(jù)的顯示外觀而不影響業(yè)務(wù)邏輯。換而言之,網(wǎng)頁設(shè)計(jì)師只需要關(guān)注設(shè)計(jì),Java開發(fā)人員只需要關(guān)注業(yè)務(wù)邏輯。
    3. 保持源代碼的安全性,保護(hù)自己的知識(shí)產(chǎn)權(quán)。


如果在你的應(yīng)用程序中使用了Enterprise JavaBeans (EJBs)組件,必須將業(yè)務(wù)邏輯保留在EJB組件中,提供生命周期管理,事務(wù)支持與對(duì)多客戶端對(duì)域?qū)ο螅▽?shí)體Beans)的存取。可以在Enterprise BluePrints 獲得更為詳細(xì)的資料。

  • 使用自定義標(biāo)記: 并不是所有HTML內(nèi)容開發(fā)者都喜歡將Java代碼(或scriptlets)嵌入在HTML文檔中的,可能是因?yàn)樗麄儾涣私釰ava語言并且也不樂意學(xué)習(xí)它的語法。但是不能使用JavaBeans組件封裝很多Java代碼,在JSP頁面中使用它們?nèi)匀灰髢?nèi)容開發(fā)者具有Java語法的知識(shí)。

    JSP技術(shù)允許你通過標(biāo)記庫設(shè)備引入新的自定義標(biāo)記。作為一個(gè)Java開發(fā)者,你可以通過引入能夠部署并在HTML這類語法中使用的自定義標(biāo)記擴(kuò)展JSP頁面。自定義標(biāo)記通過進(jìn)一步分隔業(yè)務(wù)邏輯和表示邏輯也允許你提供更好的封裝。另外,它們提供了自定義表示的方法,而使用JSTL卻很難做到這一點(diǎn)。

    自定義標(biāo)記的好處:
    1. 他們能夠消除JSP應(yīng)用程序中的scriptlets。標(biāo)記必需的參數(shù)可以作為屬性或內(nèi)容體傳遞,因此,不需要Java代碼初始化或設(shè)置組件屬性。
    2. 它們的語法非常類似。Scriptlets是使用Java代碼編寫的,但是可以在類似于HTML語法中使用自定義標(biāo)記。
    3. 它們能夠提高非程序員內(nèi)容開發(fā)者的生產(chǎn)率,允許它們執(zhí)行HTML不行完成的任務(wù)。
    4. 它們是可重用的。節(jié)省了開發(fā)和測(cè)試的時(shí)間。Scriptlets不是可重用的,除非你通過剪切粘貼 來“重用”。


簡(jiǎn)而言之,你可以使用和使用HTML創(chuàng)建表達(dá)式一樣的方法來通過自定義標(biāo)記完成復(fù)雜的任務(wù)。

編寫自定義標(biāo)記庫的時(shí)候,可以使用下列編程指南:

    1. 保持簡(jiǎn)單性:如果需要在一個(gè)標(biāo)記中包含多個(gè)屬性,那么最好將它分為多個(gè)標(biāo)記。
    2. 使它具有可用性:咨詢標(biāo)記的使用者(HTML開發(fā)者)從而獲得高可用性。
    3. 不要在JSP頁面中發(fā)明一種編程語言:不要開發(fā)自定義標(biāo)記讓用戶編寫顯式的程序。
    4. 盡量不要重新發(fā)明輪子:目前有多個(gè)JSP標(biāo)記庫可用,如Jakarta Taglibs Project。查看這些標(biāo)記庫,看看是否有你所想要的東西。
  • 不要重新發(fā)明輪子: 雖然自定義標(biāo)記提供了重用寶貴的組件的方法,但是仍然要?jiǎng)?chuàng)建、測(cè)試和調(diào)試它們。另外,開發(fā)者仍然要不斷地重新發(fā)明輪子,該解決方案的效率不是最高的。問題就是通過提供一組顆重用的標(biāo)準(zhǔn)標(biāo)記解決JavaServer Pages Standard Tag Library (JSTL) 。JSTL定義了一組在任何地方都一樣工作的標(biāo)準(zhǔn)標(biāo)記庫,這樣你就不再需要使用scriptlet(或各類供應(yīng)商提供的迭代標(biāo)記)在集合中進(jìn)行迭代。JSTL 包括各類標(biāo)記,循環(huán)、不使用Java語法就讀取屬性、迭代各類數(shù)據(jù)結(jié)構(gòu)、有條件地計(jì)算表達(dá)式、通過一種精確的方式設(shè)置屬性和腳本變量并分析XML文檔。
  • 使用JSTL表達(dá)式語言: 使用JSP范圍屬性和請(qǐng)求參數(shù)將信息傳遞給JSP頁面。表達(dá)式語言 (EL)是為頁面作者特別設(shè)計(jì)的語言,將JSP范圍屬性提升為業(yè)務(wù)邏輯到JSP頁面通訊的標(biāo)準(zhǔn)方法。然而,注意,然而EL是JSP技術(shù)的一個(gè)關(guān)鍵方面,它不是一個(gè)通用編成語言。而且,它是簡(jiǎn)單的數(shù)據(jù)存取語言,它不需要使用scriptlet或請(qǐng)求時(shí)間表達(dá)式值就能方便地存取(并操作)應(yīng)用數(shù)據(jù)。

    在JSP 1.x中,頁面作者必須使用表達(dá)式<%= aName %> 來存取系統(tǒng)的值,如下面的例子所示:
           <someTags:aTag attribute="<%=
                    pageContext.getAttribute("aName") %>">

或自定義的JavaBeans組件的值:

   <%= aCustomer.getAddress().getCountry() %>

表達(dá)式語言允許頁面作者使用簡(jiǎn)化的語法存取對(duì)象。例如,可以使用下面的語句存取簡(jiǎn)單變量:

   <someTags:aTag attribute="${aName}">

如果想要存取嵌套的JavaBeans屬性,可以使用下面的語句:

   <someTags.aTag attribute="${
      aCustomer.address.country}">

如果你使用JavaScript,你將會(huì)覺得非常熟悉,因?yàn)镋L采用JavaScript語法存取結(jié)構(gòu)化數(shù)據(jù)。

  • 如果可能使用過濾器: 過濾器是JSP技術(shù)的一項(xiàng)新功能。如果你曾經(jīng)遇到過這樣一種情況,那就是有多個(gè)servlet或JSP頁面需要壓縮它們的內(nèi)容,那么在這種情況下你就能夠編寫一個(gè)簡(jiǎn)單的壓縮過濾器并將它應(yīng)用到所有的資源上。例如,在Java BluePrints中,通過過濾器來提供SignOn。
  • 使用可移植的安全模型: 絕大多數(shù)服務(wù)器提供服務(wù)器或供應(yīng)商特定的安全功能,這樣就將開發(fā)者局限于某臺(tái)特定的服務(wù)器。為了最大化企業(yè)應(yīng)用的可移植性,使用一個(gè)可移植的Web應(yīng)用安全模型。然而,到最后,這歸結(jié)成權(quán)衡問題。例如,如果你有一組早就定義好的用戶,你可以使用基于表單的登錄或基本認(rèn)證來管理他們。但是如果你希望動(dòng)態(tài)創(chuàng)建用戶,你就需要使用容器特定的API來創(chuàng)建和管理用戶。但是容器特定的API不具有可移植性,使用適配器(Adapter)設(shè)計(jì)模式能夠克服這一點(diǎn)。
  • 使用數(shù)據(jù)庫存儲(chǔ)持久信息: 可以使用HttpSession 對(duì)象實(shí)現(xiàn)會(huì)話,該對(duì)象提供了一個(gè)簡(jiǎn)單方便的機(jī)制來存儲(chǔ)用戶、識(shí)別用戶的cookie。使用會(huì)話存儲(chǔ)臨時(shí)信息—所以即便這些信息丟失了,你也不用擔(dān)心。(當(dāng)會(huì)話過期或客戶端改變?yōu)g覽器的時(shí)候,會(huì)話數(shù)據(jù)就會(huì)丟失。) 如果你希望存儲(chǔ)持久信息,使用數(shù)據(jù)庫,在瀏覽器之間共享數(shù)據(jù)庫中的持久信息更加安全更具有可移植性。
  • 緩存內(nèi)容: 永遠(yuǎn)都不要?jiǎng)討B(tài)重新生成請(qǐng)求之間不會(huì)改變的內(nèi)容。你可以在客戶端、代理端或服務(wù)器端緩存內(nèi)容。
  • 使用連接緩沖池: 推薦使用JSTL進(jìn)行數(shù)據(jù)庫存取。但是如果你希望自己定制編寫數(shù)據(jù)庫存取的行為,推薦你使用連接池,這樣能有效地讓所有請(qǐng)求共享數(shù)據(jù)庫連接。然而,注意,J2EE服務(wù)器在背后提供了該項(xiàng)功能。
  • 緩存數(shù)據(jù)庫請(qǐng)求結(jié)果: 如果你希望緩存數(shù)據(jù)庫結(jié)果,不要使用JDBC的ResultSet 對(duì)象作為緩存對(duì)象。它和一個(gè)鏈接緊密結(jié)合,這個(gè)鏈接和連接池相沖突。將數(shù)據(jù)從ResultSet 復(fù)制到特定應(yīng)用的bean,如Vector或JDBC的RowSets。
  • 在必要的時(shí)候采取新的JSP XML語法:實(shí)際上這基于你希望你的應(yīng)用程序如何遵守XML。然而,這需要進(jìn)行權(quán)衡,因?yàn)檫@使得JSP成為更加強(qiáng)大的工具,但是對(duì)開發(fā)者卻不怎么友好。
  • 讀取并應(yīng)用Enterprise BluePrints:Sun的 Enterprise BluePrints 給開發(fā)者提供了指南、 模式、 和例子應(yīng)用程序,如Adventure Builder和Pet Store?偟膩碚f, J2EE BluePrints提供了最佳實(shí)踐和一組設(shè)計(jì)模式,這些實(shí)踐和模式是構(gòu)建具有可移植性、強(qiáng)壯可擴(kuò)展的Java應(yīng)用程序中經(jīng)常出現(xiàn)的問題的解決方案。

集成Servlets和JSP頁面

JSP規(guī)范給出了使用JSP頁面構(gòu)建Web應(yīng)用程序的兩個(gè)方案:JSP模型1和模型2體系結(jié)構(gòu)。這兩個(gè)模型的區(qū)別在于處理的位置。在模型1的體系結(jié)構(gòu)中,如圖2所示,JSP頁面負(fù)責(zé)處理請(qǐng)求并將響應(yīng)發(fā)送給客戶端。


2: JSP模型1 體系結(jié)構(gòu)

模型2體系結(jié)構(gòu),如圖3所示,集成使用了servlets 和JSP頁面。在該模型中,JSP頁面用于表示層,并且servlets負(fù)責(zé)處理各類任務(wù)。Servlet作為一個(gè)控制器,負(fù)責(zé)處理請(qǐng)求并創(chuàng)建JSP頁面所需的任何bean。該控制器也負(fù)責(zé)確定將該請(qǐng)求傳遞到哪個(gè)JSP頁面。JSP頁面檢索servlet創(chuàng)建的對(duì)象,并提取動(dòng)態(tài)內(nèi)容插入在一個(gè)模板中。


3: JSP模型 2 體系結(jié)構(gòu)

該模型促進(jìn)了模型視圖控制器(MVC)體系結(jié)構(gòu)風(fēng)格設(shè)計(jì)模式的使用。注意,早就存在多個(gè)框架能夠?qū)崿F(xiàn)該有用的設(shè)計(jì)模式,并將內(nèi)容和表示真正地獨(dú)立開來。Apache Struts是MVC的形式化框架。該框架非常適用于復(fù)雜的應(yīng)用程序,在這些復(fù)雜的應(yīng)用程序中單個(gè)請(qǐng)求或表單提交會(huì)產(chǎn)生看起來截然不同的結(jié)果。

結(jié)束語

最佳實(shí)踐—事實(shí)證明是經(jīng)常重復(fù)出現(xiàn)的問題的解決方案—產(chǎn)生了高質(zhì)量的應(yīng)用程序。本文是開發(fā)servlet時(shí)需要遵守的多個(gè)指南和最佳實(shí)踐-和基于JSP的Web應(yīng)用程序。

請(qǐng)留心servlets和JSP技術(shù),因?yàn)樵谶@些技術(shù)中有許多激動(dòng)人心的東西。例如,JavaServer Faces (JFC),是一個(gè)Java程序社區(qū)(Java Community Process),它的目標(biāo)是定義一個(gè)標(biāo)準(zhǔn)的Web應(yīng)用框架,這將很好地和Apache Struts集成。