《Web開發(fā)技術(shù)》課件第7章_第1頁
《Web開發(fā)技術(shù)》課件第7章_第2頁
《Web開發(fā)技術(shù)》課件第7章_第3頁
《Web開發(fā)技術(shù)》課件第7章_第4頁
《Web開發(fā)技術(shù)》課件第7章_第5頁
已閱讀5頁,還剩167頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

第7章Web服務(wù)器端編程與JavaServlet7.1Web服務(wù)器端編程概述

7.2客戶端數(shù)據(jù)的提交和服務(wù)器端的提取7.3Web程序中數(shù)據(jù)的分類7.4Web數(shù)據(jù)傳輸協(xié)議——HTTP7.5Servlet的提出和工作原理7.6Servlet的設(shè)計和實現(xiàn)

7.7ServletAPI常用接口和類7.8Servlet應(yīng)用實例習(xí)題

7.1Web服務(wù)器端編程概述

Web服務(wù)器端編程負(fù)責(zé)完成在服務(wù)器端運行的程序的設(shè)計和編碼,這些程序的主要功能一般是進行業(yè)務(wù)邏輯的處理。通常的做法是數(shù)據(jù)的存儲使用數(shù)據(jù)庫系統(tǒng)及文件系統(tǒng),通過使用數(shù)據(jù)庫訪問接口訪問數(shù)據(jù)庫系統(tǒng)中存儲的數(shù)據(jù),根據(jù)應(yīng)用系統(tǒng)業(yè)務(wù)邏輯對這些數(shù)據(jù)進行處理,然后把相關(guān)處理結(jié)果發(fā)送到客戶端,或者存儲到文件或數(shù)據(jù)庫系統(tǒng)中。Web服務(wù)器端編程模型如圖7.1所示。圖7.1Web服務(wù)器端編程模型根據(jù)以上模型可知,開發(fā)Web系統(tǒng)首要的工作就是系統(tǒng)模塊劃分。從邏輯層次上可以將系統(tǒng)模塊劃分為如下三層:

(1)界面層:主要用于界面展示、客戶輸入數(shù)據(jù)。該部分用HTML(HyperTextMarkupLanguage)格式的文件作為客戶端軟件解析、顯示的數(shù)據(jù)文件,即通常所說的網(wǎng)頁。在HTML文件中可以包含在客戶端瀏覽器環(huán)境下解釋執(zhí)行的客戶端腳本(如受瀏覽器支持的廣泛使用的JavaScript腳本)、用來控制顯示樣式的CSS(CascadingStyleSheets)文件、用來繪制動態(tài)圖形和完成簡單客戶端功能的JavaApplet等。

(2)應(yīng)用邏輯處理層:也稱為業(yè)務(wù)處理層,主要完成系統(tǒng)數(shù)據(jù)處理,是系統(tǒng)的核心。數(shù)據(jù)是業(yè)務(wù)在計算機中的表示,根據(jù)系統(tǒng)業(yè)務(wù)流程設(shè)計出程序流程圖,進而去編碼實現(xiàn)。根據(jù)服務(wù)器支持的運行環(huán)境,可選用不同的開發(fā)腳本語言。如果服務(wù)器端具備Java運行環(huán)境,可以使用JSP(JavaServerPages)腳本、Servlet程序;如果具備PHP(HypertextPreprocessor)運行環(huán)境,可以使用PHP腳本。當(dāng)今可以選用的開發(fā)腳本語言多達十多種,在制定系統(tǒng)方案時,可以根據(jù)系統(tǒng)應(yīng)用環(huán)境和成本、開發(fā)難度,選取一種開發(fā)腳本語言來作為系統(tǒng)開發(fā)腳本語言。

(3)數(shù)據(jù)存儲層:用來存儲數(shù)據(jù),依據(jù)系統(tǒng)設(shè)計階段設(shè)計的數(shù)據(jù)字典,將系統(tǒng)數(shù)據(jù)存儲在數(shù)據(jù)庫系統(tǒng)文件中,然后通過數(shù)據(jù)庫訪問接口訪問該數(shù)據(jù)庫系統(tǒng)中的數(shù)據(jù)。數(shù)據(jù)庫的系統(tǒng)維護和管理由數(shù)據(jù)庫系統(tǒng)管理員負(fù)責(zé),數(shù)據(jù)庫數(shù)據(jù)的訪問通過腳本程序進行,這就實現(xiàn)了數(shù)據(jù)庫的透明訪問,提高了系統(tǒng)的安全性和可靠性。

該種劃分法從邏輯層次到物理實現(xiàn)的映射可用圖7.2來表示。系統(tǒng)設(shè)計和分析人員通常根據(jù)這種邏輯劃分來分析和定義系統(tǒng)模塊。程序設(shè)計的流程按照數(shù)據(jù)的讀取、保存和處理來分別進行。由于采用了數(shù)據(jù)庫系統(tǒng),故數(shù)據(jù)的讀取和保存變得容易,使程序設(shè)計者能夠把主要精力放在業(yè)務(wù)流程對應(yīng)的數(shù)據(jù)處理上。系統(tǒng)和用戶的交互界面一般是瀏覽器支持的GUI圖形界面,即由文本、圖片、表單構(gòu)成的頁面,程序設(shè)計者應(yīng)該站到系統(tǒng)界面的角度去設(shè)計頁面,與傳統(tǒng)的主要用來展示文本內(nèi)容的網(wǎng)頁區(qū)分開來。圖7.2Web應(yīng)用程序從邏輯層次到物理實現(xiàn)的映射7.2客戶端數(shù)據(jù)的提交和服務(wù)器端的提取

客戶端用戶向服務(wù)器端程序提交數(shù)據(jù)主要通過表單來進行。關(guān)于表單的標(biāo)準(zhǔn)理論請參考網(wǎng)上文檔,網(wǎng)址為/TR/html401/interact/forms.html#h-17.1。表單(Form)是對客戶端瀏覽器軟件向服務(wù)器端程序提交的數(shù)據(jù)進行封裝的控件。提供給編程人員的接口是表單和表單項。表單項的名稱用來關(guān)聯(lián)數(shù)據(jù)項名稱,在軟件中常把這種方法叫做“Key-Value”,即鍵—值對,鍵即表單項名稱,值即填入表單控件中的文本。服務(wù)器端程序提取數(shù)據(jù)時主要通過表單項來獲取對應(yīng)值,然后使用這些數(shù)據(jù)進行處理。表單通過如下形式

定義:

<formname=“l(fā)ogin”action=“forward.jsp”method=“get”>

<inputtype=“text”name=“username”value=“l(fā)iuyongping”>

</form>

<formname=“form1”action=“process.jsp”method=“post”>

</form>

其中,action和method屬性非常關(guān)鍵。action屬性定義了該表單信息和哪個文件相關(guān)聯(lián),即由哪個服務(wù)器端程序來提取和處理該表單數(shù)據(jù)。如在此例中由process.jsp這個程序來處理該表單數(shù)據(jù)。method屬性定義了該表單信息的傳送(傳輸)方式,可選post和get中的任意一種。采用post方式時,表單的數(shù)據(jù)是被客戶端瀏覽器封裝在請求消息體中來進行傳送的,故保密性強。而采用get方式時,表單的數(shù)據(jù)是附在URL之后,以問號“?”隔開,數(shù)據(jù)以name=value對的形式出現(xiàn)的,多個數(shù)據(jù)對使用符號“&”隔開。get方式常用于少量數(shù)據(jù)傳送(<1KByte),由于發(fā)送時數(shù)據(jù)顯示在瀏覽器地址欄中,容易被看到和記錄,故保密性差。

【例7.1】以get方式向服務(wù)器提交表單數(shù)據(jù),該表單完成用戶名和密碼的提交,如圖7.3所示。請注意觀察圖7.4的URL地址欄內(nèi)容。圖7.3登錄界面源文件login_get_method.html內(nèi)容如下:

<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01

Transitional//EN”“/TR/html4/loose.dtd”>

<html>

<head>

<metahttp-equiv=“Content-Type”content=“text/html;

charset=gb2312”>

<title>登錄模塊</title>

</head>

<bodybgcolor=“FFFFFF”>

<h1align="center"><b>歡迎登錄系統(tǒng)</b></h1>

<formaction=“forward.jsp”method=“get”>

<!--指定由forward.jsp來處理該表單,提交數(shù)據(jù)方式為post-->

<p></p>

<!--以2行2列的表格來布局-->

<tablewidth=“52%”border=“2”align=“center”>

<trbgcolor=“#FFFFCC”>

<tdalign=“center”width=“43%”><divalign=“center”>用戶名:

</div></td>

<tdwidth=“57%”><divalign=“l(fā)eft”>

<inputtype=“text”name=“username”>

</div></td>

</tr>

<trbgcolor=“#CCFF99”>

<tdalign=“center”width=“43%”><divalign=“center”>密碼:</div></td>

<tdwidth=“57”><divalign=“l(fā)eft”>

<inputtype=“password”name=“password”>

</div></td>

</tr>

</table>

<!--以段的形式來組織兩個按鈕-->

<palign=“center”>

<inputtype=“reset”name=“Reset”value=“重置”>

<inputtype=“submit”name=“Submit2”value=“提交”>

</p>

</form>

</body>

</html>

源文件forward.jsp內(nèi)容如下:

<%@pagelanguage=“java”contentType=“text/html;

charset=gb2312”

pageEncoding="gb2312"%>

<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01

Transitional//EN”“/TR/html4/loose.dtd”>

<html>

<head>

<metahttp-equiv=“Content-Type”content=“text/html;

charset=gb2312”>

<title>loginforward</title>

</head>

<body>

<%

Stringusername=null;

Stringpassword=null;

request.setCharacterEncoding(“gb2312”);

username=request.getParameter(“username”);

password=request.getParameter(“password”);

if(!username.equals(“”)&&!password.equals(“”))

{

%>

<jsp:forwardpage=“l(fā)ogin_ok.jsp”>

<jsp:paramname=“username”value=‘<%=username%>’/>

<jsp:paramname="username"value='<%=password%>'/>

</jsp:forward>

<%

}

else

{

%>

<jsp:forwardpage=“error.jsp”>

<jsp:paramname=“username”value=‘<%=username%>’/>

<jsp:paramname=“username”value=‘<%=password%>’/>

</jsp:forward>

<%

}

%>

</body>

</html>

其中,login_ok.jsp和error.jsp文件源代碼請參考9.6.1小節(jié)的例9.1中這兩個文件的源代碼。該實例運行結(jié)果如圖7.4所示。圖7.4處理數(shù)據(jù)界面

1.表單數(shù)據(jù)的填入

當(dāng)表單中的輸入控件項獲得焦點時,用戶輸入或者選擇數(shù)據(jù)。表單中可使用的控件有文本輸入控件、密碼輸入控件、單選控件、復(fù)選控件等。

【例7.2】以post方式向服務(wù)器提交表單數(shù)據(jù),該表單發(fā)送某單位工作人員的周小結(jié)給部門經(jīng)理,供部門經(jīng)理閱讀,界面如圖7.5所示。注意與例7.1的以get方式提交數(shù)據(jù)進行比較。圖7.5表單界面源文件weeklog.html內(nèi)容如下:

<!DOCTYPEhtmlPUBLIC“-//W3C//DTDXHTML1.0Strict//EN”

“/TR/xhtml1/DTD/xhtml1-strict.dtd”>

<htmlxmlns=“/1999/xhtml”>

<head><metahttp-equiv=“Content-Type”content=“text/html;

charset=gb2312”>

<title>工作周志</title></head>

<body>

<formaction=“process.jsp”method=“post”>

<div><center>

<label>姓名<inputtype=“text”name=“username”

size=“10”/>

</label><br/><br/><label>周小結(jié)<br/>

<textareaname=“weeklog”rows=“5”

cols=“60”></textarea>

</label><br/>

完成情況

<label>

<inputtype=“radio”name=“boxgroup1”value

=“非常好”/>非常好

</label>

<label>

<inputtype=“radio”name=“boxgroup1”value

=“完成”/>完成

</label>

<label>

<inputtype=“radio”name=“boxgroup1”value

=“未完成”/>未完成

</label><br/><br/>

<inputtype=“submit”name=“doit”value=“提交”/>

</center></div>

</form>

</body>

</html>

其中,<metahttp-equiv=“Content-Type”content=“text/html;charset=gb2312”>中的meta標(biāo)簽的charset屬性指定請求信息的編碼方式為支持中文字符的gb2312編碼方式,如果不指定其編碼方式,在服務(wù)器端獲取中文時可能出現(xiàn)亂碼。

當(dāng)表單中的控件獲得輸入焦點后,用戶輸入數(shù)據(jù),點擊“提交”按鈕,客戶端瀏覽器軟件完成表單數(shù)據(jù)的封裝和發(fā)送。

2.表單數(shù)據(jù)的傳送

表單數(shù)據(jù)被客戶端軟件封裝后通過網(wǎng)絡(luò)傳送到服務(wù)器端,傳送的方式由表單的method屬性指定。如果選擇的是post方式,數(shù)據(jù)放在HTTP請求消息體中;如果選擇的是get方式,數(shù)據(jù)放在HTTP請求消息頭中。服務(wù)器如Tomcat把HTTP請求消息用Java語言封裝成HttpServletRequest對象。

3.表單數(shù)據(jù)的提取

服務(wù)器軟件接收到傳送來的請求消息后,先進行消息解析,然后根據(jù)流程進行處理,最后將處理結(jié)果通過響應(yīng)消息返回給客戶端軟件。如果由JSP引擎來接收消息,該引擎將消息封裝成HttpServletRequest類型的對象并提供給JSP程序訪問,通過調(diào)用HttpServletRequest類型的對象request的方法getParameter(Stringname)來完成數(shù)據(jù)的提取。該方法的原型為ObjectgetParameter(Stringname),如提取例7.1和例7.2中的用戶名和周小結(jié)數(shù)據(jù),可使用如下語句:

Stringstr_Username=request.getParameter(“username”);

Stringstr_Weeklog=request.getParameter("weeklog");

【例7.3】提取表單數(shù)據(jù)示例。提取例7.2中的表單數(shù)據(jù)并顯示在頁面上,顯示結(jié)果如圖7.6所示。

源文件process.jsp代碼如下:

<%@pagelanguage=“java”contentType=“text/html;

charset=gb2312”

pageEncoding=“gb2312”%>

<html><head>

<metahttp-equiv=“Content-Type”content=“text/html;

charset=gb2312”>

<title>提取表單數(shù)據(jù)</title></head>

<body>

<%

request.setCharacterEncoding(“gb2312”);

response.setContentType(“text/html;charset=gb2312”);

out.println(request.getParameter(“username”));

out.println(request.getParameter(“weeklog”));

out.println(request.getParameter(“boxgroup1”));

%>

</body></html>圖7.6處理數(shù)據(jù)界面

7.3Web程序中數(shù)據(jù)的分類

Web應(yīng)用程序?qū)Υ罅繑?shù)據(jù)進行處理時,這些數(shù)據(jù)的表示方式、存儲方式、使用范圍和使用時限各不相同,為此,需要分類來進行表示。按數(shù)據(jù)的使用范圍可將Web應(yīng)用程序中的數(shù)據(jù)分為全局?jǐn)?shù)據(jù)、頁面內(nèi)數(shù)據(jù)和方法體內(nèi)數(shù)據(jù),如圖7.7所示。圖7.7Web應(yīng)用程序中數(shù)據(jù)的劃分

1.全局?jǐn)?shù)據(jù)

模塊(多個文件)之間需要通過全局?jǐn)?shù)據(jù)來交換信息,這類型的數(shù)據(jù)由系統(tǒng)開辟一塊公共存儲區(qū)進行存放,供各文件訪問。JSP系統(tǒng)提供了application、session、servletcontext等全局?jǐn)?shù)據(jù)對象,開發(fā)者可以方便地使用這些對象完成模塊之間的數(shù)據(jù)交換。

在實際應(yīng)用中,需要記錄和跟蹤用戶訪問系統(tǒng)的情況,此時需要使用全局?jǐn)?shù)據(jù)對象session。用戶在訪問不同的頁面并完成一次與系統(tǒng)的交互后,相關(guān)信息可以保存到session對象中,通過調(diào)用session對象提供的getSession和setSession方法完成從ession對象中讀取數(shù)據(jù)和向session對象中寫入數(shù)據(jù)。session數(shù)據(jù)區(qū)示意圖如圖7.8所示。圖7.8session數(shù)據(jù)區(qū)示意圖

2.頁面內(nèi)數(shù)據(jù)

頁面內(nèi)數(shù)據(jù)的可見范圍為頁面,有效期為頁面初始化到頁面執(zhí)行結(jié)束,它為頁面內(nèi)不同方法之間進行數(shù)據(jù)交換提供了途徑。JSP系統(tǒng)定義的頁面內(nèi)數(shù)據(jù)對象有page、pageContext、out、request、response、exception等,開發(fā)者可以采用類似<%!Stringstr=null;%>的語法定義各種類型的對象。一個頁面被Servlet翻譯成一個Servlet對象,頁面內(nèi)數(shù)據(jù)被Servlet翻譯成Servlet類的公共數(shù)據(jù),供Servlet的各個方法相互訪問。

3.方法體內(nèi)數(shù)據(jù)

方法體內(nèi)數(shù)據(jù)即局部變量,其可見范圍為Java類的方法體內(nèi)。JSP系統(tǒng)在腳本<%%>中定義的對象即屬于局部對象,如果數(shù)據(jù)只在方法內(nèi)使用,則定義為方法體內(nèi)數(shù)據(jù)。

在一個具體的應(yīng)用系統(tǒng)中,用戶的鑒權(quán)、認(rèn)證、跟蹤一般是必需的,Web系統(tǒng)廣泛采用的是cookie和session兩種機制。cookie用來在客戶端記錄信息,session用來在服務(wù)器端記錄信息。cookie是客戶端通過開辟一個文件供服務(wù)器端程序動態(tài)地寫入和讀出的信息集合體,服務(wù)器端程序生成cookie內(nèi)容并填入響應(yīng)消息的特定字段,再傳輸?shù)娇蛻舳?,由客戶端寫入文件保存??蛻舳讼蚍?wù)器端傳輸請求信息時,可以把cookie內(nèi)容傳輸?shù)椒?wù)器端,供服務(wù)器程序處理。

【例7.4】通過session對象保存用戶名和密碼,記錄和跟蹤系統(tǒng)用戶信息。登錄界面如圖7.9所示,登錄成功后的界面如圖7.10所示,使用系統(tǒng)業(yè)務(wù)功能界面如圖7.11所示。圖7.9登錄界面源文件firstlogin.html內(nèi)容如下:

<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01

Transitional//EN”“/TR/html4/loose.dtd”>

<html>

<head>

<metahttp-equiv=“Content-Type”content=“text/html;

charset=gb2312”>

<title>登錄模塊</title>

</head>

<bodybgcolor=“FFFFFF”>

<h1align="center"><b>歡迎登錄系統(tǒng)</b></h1>

<formaction=“savelogin.jsp”method=“post”>

<!--指定由savelogin.jsp來處理該表單,提交數(shù)據(jù)方式為post-->

<p></p>

<!--以2行2列的表格來布局-->

<tablewidth=“52%”border=“2”align=“center”>

<trbgcolor=“#FFFFCC”>

<tdalign=“center”width=“43%”><divalign=“center”>用戶名:</div></td>

<tdwidth=“57%”><divalign=“l(fā)eft”>

<inputtype="text"name="username">

</div></td>

</tr>

<trbgcolor=“#CCFF99”>

<tdalign=“center”width=“43%”><divalign=“center”>密碼:</div></td>

<tdwidth=“57”><divalign=“l(fā)eft”>

<inputtype=“password”name=“password”>

</div></td>

</tr>

</table>

<!--以段的形式來組織兩個按鈕-->

<palign=“center”>

<inputtype=“reset”name=“Reset”value=“重置”>

<inputtype=“submit”name=“Submit2”value=“提交”>

</p>

</form>

</body>

</html>圖7.10登錄成功后的界面源文件savelogin.jsp內(nèi)容如下:

<%@pagelanguage=“java”contentType=“text/html;

charset=gb2312”

pageEncoding=“gb2312”%>

<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01Transitional//EN”

“/TR/html4/loose.dtd”>

<html>

<head>

<metahttp-equiv=“Content-Type”content=“text/html;

charset=gb2312">

<title>Savelogininformation</title>

</head>

<body>

<%!Stringurl=null;%>

<%

Stringusername=null;

Stringpassword=null;

request.setCharacterEncoding(“gb2312”);

response.setContentType(“text/html;charset=gb2312”);

username=request.getParameter("username");

password=request.getParameter(“password”);

session.setAttribute(“username”,username);

session.setAttribute(“password”,password);

url=response.encodeURL(“business.jsp”);

%>

<ahref=‘<%=url%>’>usesystem!</a>

</body>

</html>圖7.11使用系統(tǒng)業(yè)務(wù)功能界面源文件business.jsp內(nèi)容如下:

<%@pagelanguage=“java”contentType=“text/html;

charset=gb2312”

pageEncoding=“gb2312”%>

<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01

Transitional//EN”

“/TR/html4/loose.dtd”>

<html>

<head>

<metahttp-equiv=“Content-Type”content=“text/html;

charset=gb2312">

<title>Usesystem</title>

</head>

<body>

<%

Stringusername;

Stringpassword;

username=(String)session.getAttribute(“username”);

password=(String)session.getAttribute(“password”);

out.println(“Currentuser[<fontcolor=red>”+username+“</font>]”);

%>

</body>

</html>

【例7.5】寫入cookie信息和從cookie中讀出信息,用于客戶端跟蹤和驗證。寫入cookie信息界面如圖7.12所示,讀出cookie信息界面如圖7.13所示。圖7.12寫入cookie信息界面源文件writecookie.jsp內(nèi)容如下:

<%@pagelanguage=“java”contentType=“text/html;charset=ISO-8859-1”

pageEncoding=“ISO-8859-1”%>

<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01

Transitional//EN”“/TR/html4/loose.dtd”>

<html>

<head>

<metahttp-equiv="Content-Type"content="text/html;charset=ISO-8859-1">

<title>writecookie</title>

</head>

<body>

<divalign=“center”>writecookie</div>

<%

Cookiecook=newCookie(“KeyName”,“Iamakeyvalue”);

cook.setMaxAge(30*60);

response.addCookie(cook);

out.print(“Finishingwritecookie”);

%>

<br>

<br>

<ahref=“readcookie.jsp”>readcookie

</body>

</html>圖7.13讀出cookie信息界面源文件readcookie.jsp內(nèi)容如下:

<%@pagelanguage=“java”contentType=“text/html;charset=ISO-8859-1”

pageEncoding=“ISO-8859-1”%>

<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01Transitional//EN”

“/TR/html4/loose.dtd”>

<html>

<head>

<metahttp-equiv=“Content-Type”content=“text/html;

charset=ISO-8859-1">

<title>readcookie</title>

</head>

<body>

<%

Cookiecookies[]=request.getCookies();

CookiesCookie=null;

StringstrValue=null;

StringstrKeyName=null;

if(cookies==null)

{

out.println("nocookierecord");

}

else

{

out.println(“<br>thenumberofcookie:”+cookies.length);

for(inti=0;i<cookies.length;i++)

{

sCookie=cookies[i];

strKeyName=sCookie.getName();

strValue=sCookie.getValue();

out.println(“<br>cookiekeyname:”+strKeyName+“,

thevalueof:”+strValue);

}

7.4Web數(shù)據(jù)傳輸協(xié)議——HTTP

Web服務(wù)器軟件和客戶端軟件之間的通信一般使用HTTP或HTTPS協(xié)議。HTTP(HypertextTransferProtocol,超文本傳輸協(xié)議)主要用來在網(wǎng)絡(luò)上傳輸文本內(nèi)容,采用請求/響應(yīng)的模式來工作,如圖7.14所示。圖7.14HTTP協(xié)議示例圖

HTTP協(xié)議包括兩種類型的消息,分別是請求消息和響應(yīng)消息。請求消息用來發(fā)送請求內(nèi)容,響應(yīng)消息用來攜帶返回服務(wù)器端的處理結(jié)果內(nèi)容。響應(yīng)消息經(jīng)常返回一個服務(wù)器的資源文件,如HTML文件等。

兩種類型的消息字段如圖7.15所示。圖7.15HTTP消息示例下面是一個HTTP請求消息的例子。

Get/sample.jspHTTP/1.1

Accept:image/gif,image/jpeg,*/*

Accept-Language:zh-cn

Connection:Keep-Alive

Host:localhost

User-Agent:Mozilla/4.0(compatible;MSIE5.01;WindowsNT5.0)

Accept-Encoding:gzip,deflate

Username=liuyongping&password=liuyongping

HTTP請求消息一般包含如下三部分:

第一部分:請求方法URI協(xié)議/版本。上面的請求消息示例第一行即指名請求方法為Get,請求的文件為?/sample.jsp,協(xié)議為HTTP,版本號為1.1。其中HTTP1.1支持get、post、head、put、delete、trace、options請求方法,如表7.1所示。其中g(shù)et和post是最常用的請求方法。該部分的URI完整地指定了要訪問的網(wǎng)絡(luò)資源,通常只要給出相對于服務(wù)器的根目錄的相對目錄即可,因此總是以“/”開頭。緊接著是協(xié)議名稱,最后以“/”分割后面的版本號說明,即所使用的HTTP的版本。

get方法通常只用于請求指定服務(wù)器上的資源,這種資源可以是靜態(tài)的HTML頁面或其他文件,也可以是由CGI程序生成的結(jié)果數(shù)據(jù)。使用get方法請求文件也可以向服務(wù)器傳送一些數(shù)據(jù),例如:

get/login.jsp?name=liuyongping&password=***HTTP/1.1

以post方法提交的數(shù)據(jù)是通過消息體的形式進行傳送的,提交的數(shù)據(jù)量一般比較大,而且比較安全,例如:

<formname="form1"method="post"action="showdata.jsp">第二部分:請求頭。該部分包含許多客戶端環(huán)境信息和請求體的重要信息,具體可包含Accept、Accept-Language、Use-Agent、Ua-Cpu、Accept-Encoding、Host、Connnection、Cookie等字段。上面的請求消息示例從第二行到“Accept-Encoding:gzip,deflate”行結(jié)尾部分都為請求頭部分。

第三部分:請求正文。上面的請求消息示例的請求頭下面隔一個空行后即為正文部分,或稱為請求消息體。該部分可以包含客戶提交的查詢字符串信息等。請求頭部分和請求正文部分的分割是一個空行。響應(yīng)消息也由三部分組成:第一行為第一部分,如“HTTP/1.1200OK”,其中HTTP是協(xié)議說明,1.1是版本號,200是響應(yīng)碼,“OK”是響應(yīng)碼說明;第二部分為響應(yīng)消息頭,包含Server、Date、Content-Type、Last-Modified、Content-Length等字段,這些字段用來說明響應(yīng)信息內(nèi)容的重要屬性,如內(nèi)容的類型(編碼方式)、內(nèi)容的長度等,客戶端軟件可根據(jù)此處理消息體內(nèi)容;第三部分為消息內(nèi)容體,若響應(yīng)頭Content-Type字段為text/html,則該部分消息內(nèi)容為超文本字符。消息頭和消息體之間通過一個空行分隔。下面是一個HTTP響應(yīng)消息的例子,顯示結(jié)果如圖7.16

所示。圖7.16HTTP響應(yīng)體內(nèi)容顯示

HTTP/1.1200OK

Server:ApacheTomcat/6.0.10

Date:Mon,6Oct200313:13:33GMT

Content-Type:text/html

Last-Modified:Mon,6Oct200313:23:42GMT

Content-Length:112

<html>

<head>

<title>HTTPresponseexample</title>

</head>

<body>

ThisisHTTPresponsebodycontent.

</body>

</html>

【例7.6】使用Java語言實現(xiàn)一個簡單的Web服務(wù)器。該Web服務(wù)器的服務(wù)端口為1000,用戶使用瀏覽器和該服務(wù)器交互。在瀏覽器地址欄中輸入“http://localhost:1000/”,服務(wù)器接收到該命令請求后,在控制臺上打印該HTTP請求信息內(nèi)容,并向客戶端返回一個只有文本“SimpleWebServer”的頁面。源程序文件SimpleWebServer.java如下:

packagecom.test.java;

importjava.io.*;

import.*;

import.ssl.*;

publicclassSimpleWebServer

{

publicstaticvoidprocess()throwsIOException

{

ServerSocketServSock=newServerSocket(1000);

//在1000端口上監(jiān)聽客戶端請求

while(true)

{

try

{

Socketsock=ServSock.accept(); OutputStreamout=sock.getOutputStream();

//關(guān)聯(lián)輸出字節(jié)流,用來寫數(shù)據(jù)

BufferedReaderin=new

BufferedReader(newInputStreamReader(sock.getInputStream()));

//關(guān)聯(lián)輸入字節(jié)流,將字節(jié)流轉(zhuǎn)化為字符流,封裝為

帶緩沖的字符流,一次讀

//取一個文本行數(shù)據(jù)

//讀取請求并顯示到頁面上

Stringline=null;

while(((line=in.readLine())!=null)&&

(!("".equals(line)))) {

System.out.println(line);

}

System.out.println(“”);

//構(gòu)造響應(yīng)消息

StringBufferbuffer=newStringBuffer();

buffer.append(“<head><title>SimpleWebServer

</title></head>\n");

buffer.append("<body>\n");

buffer.append("SimpleWebServer\n"); buffer.append(“</body>\n”);

buffer.append(“</html>\n”);

//求取發(fā)送內(nèi)容的長度

Stringstr=buffer.toString();

byte[]data=str.getBytes();

out.write(“HTTP/1.0200OK\n”.getBytes());

out.write(newString(“Content-Length:”+

data.length+"\n").getBytes());

out.write("Content-Type:text/html\n".getBytes()); out.write(data);

out.flush();

//關(guān)閉流和端口

out.close();

in.close();

sock.close();

}

catch(Exceptione)

{

e.printStackTrace(); }

}

}

publicstaticvoidmain(String[]args)throwsIOException

{

process();

}

}

執(zhí)行時控制臺打印出的HTTP請求消息內(nèi)容如下:

GET/HTTP/1.1

Accept:image/gif,image/jpeg,image/pjpeg,image/pjpeg,

application/vnd.ms-excel,application/vnd.ms-powerpoint,

application/msword,application/x-silverlight,application/x-shockwave-flash,*/*

Accept-Language:zh-cn

User-Agent:Mozilla/4.0(compatible;MSIE8.0;WindowsNT5.1;Trident/4.0)

UA-CPU:x86

Accept-Encoding:gzip,deflate

Host:localhost:1000

Connection:Keep-Alive

GET/favicon.icoHTTP/1.1

Accept:*/*

UA-CPU:x86

Accept-Encoding:gzip,deflate

User-Agent:Mozilla/4.0(compatible;MSIE8.0;WindowsNT5.1;Trident/4.0)

Host:localhost:1000

Connection:Keep-Alive

客戶端瀏覽器的結(jié)果如圖7.17所示。圖7.17客戶端瀏覽器頁面請使用網(wǎng)絡(luò)協(xié)議分析器Ethereal(已更名為Wireshark,可到網(wǎng)站下載)安裝并捕獲分組、分析分組以及HTTP協(xié)議內(nèi)容和工作過程。Wireshark工作臺主界面如圖7.18所示。圖7.18Wireshark工作臺主界面

7.5Servlet的提出和工作原理

在Web層次模型中,Web服務(wù)器端程序的核心功能是業(yè)務(wù)邏輯數(shù)據(jù)的處理。當(dāng)服務(wù)器接收到客戶端通過網(wǎng)絡(luò)傳輸?shù)腍TTP、HTTPS請求數(shù)據(jù)后,需要按照設(shè)計的業(yè)務(wù)數(shù)據(jù)處理流程進行處理,處理完成之后構(gòu)造響應(yīng)消息返回給客戶端??蛻舳耸荳eb系統(tǒng)的輸入、輸出界面。業(yè)務(wù)邏輯數(shù)據(jù)的處理可以通過定義Servlet來完成。

Servlet對業(yè)務(wù)流程數(shù)據(jù)按業(yè)務(wù)流程進行處理,其中業(yè)務(wù)數(shù)據(jù)可能來自請求,也可能來自公共存儲區(qū)對象,處理結(jié)果數(shù)據(jù)可以更新公共存儲區(qū)對象,也可以構(gòu)造響應(yīng)消息返回給客戶端。最常見的輸出是通過響應(yīng)消息輸出到客戶端,輸出數(shù)據(jù)利用輸出流來緩存,數(shù)據(jù)主要是文本。

開發(fā)Servlet時要重點把握數(shù)據(jù)的來源(輸入)、處理、輸出,可以簡單總結(jié)為“分析請求消息”、“處理消息”、“構(gòu)造響應(yīng)消息”三個步驟。一般將每個步驟的執(zhí)行代碼分別放在不同的方法體內(nèi),這樣Servlet運行環(huán)境在調(diào)用Servlet方法時可以根據(jù)不同的步驟調(diào)用不同的方法。

Servlet是用Java語言編寫的特殊的類,該類對象的創(chuàng)建(為對象分配內(nèi)存)、初始化和方法調(diào)用由服務(wù)器軟件負(fù)責(zé),開發(fā)人員只需要搞清楚調(diào)用時刻和調(diào)用參數(shù),再通過直接繼承javax.servlet.http.HttpServlet,覆蓋Servlet的部分方法(函數(shù))就可以快速定義和實現(xiàn)一個Servlet。這些方法有doGet()、doPost()等,用于處理HTTP請求。

Servlet對象和Servletr容器的通信主要通過參數(shù)傳遞進行,由Servlet容器來判斷Servlet對象的調(diào)用時刻和調(diào)用方法。Servlet對象的生命過程如圖7.19所示。Servlet容器負(fù)責(zé)管理Servlet對象,它裝入(創(chuàng)建)對象、初始化Servlet(調(diào)用init()方法)、調(diào)度Servlet的方法、銷毀Servlet對象(釋放內(nèi)存)。圖7.19Servlet對象的生命過程

Servlet容器響應(yīng)Web客戶請求的工作過程如下:

(1)?Web客戶向Web服務(wù)器發(fā)出HTTP請求。

(2)?Web服務(wù)器解析該請求。

(3)?Servlet容器創(chuàng)建一個封裝HTTP請求消息的HttpRequest對象。

(4)Servlet容器創(chuàng)建一個HttpResponse對象,該對象是HTTP響應(yīng)消息的封裝。HttpRequest對象和HttpResponse對象是容器調(diào)用Servlet的service方法傳入的參數(shù)對象引用(Reference)。Servlet處理HttpRequest對象的結(jié)果寫入HttpResponse對象,Servlet容器從HttpResponse對象數(shù)據(jù)獲取Servlet的處理結(jié)果。

(5)Servlet容器調(diào)用HttpServlet的service方法,把HttpRequest和HttpReponse對象作為service方法的參數(shù)傳遞給HttpServlet對象。

(6)?HttpServlet調(diào)用HttpRequest的相關(guān)方法,獲取HTTP請求信息。

(7)?HttpServlet調(diào)用HttpResponse的相關(guān)方法,構(gòu)造生成響應(yīng)消息數(shù)據(jù)。

(8)?Web服務(wù)器將HttpServlet的響應(yīng)結(jié)果傳給Web客戶。

關(guān)于Servlet的功能和工作過程可以參考Servlet規(guī)范的制定者Sun公司在網(wǎng)站上發(fā)表的文章,地址為/pub/a/onjava/2003/05/14/java_webserver.html。7.6Servlet的設(shè)計和實現(xiàn)

Servlet的設(shè)計主要是繼承javax.servlet.http.HttpServlet類,覆蓋doGet()、doPost()方法。在方法體中分析請求消息javax.servlet.http.HttpServletrequest對象request,處理消息,最后構(gòu)造響應(yīng)消息javax.servlet.http.HttpServletResponse對象response,將結(jié)果數(shù)據(jù)輸出到界面。

在分析request對象中的數(shù)據(jù)時,常使用的方法是:

java.lang.StringgetParameter(java.lang.String

name)

java.util.EnumerationgetParameterNames()

java.lang.String[]getParameterValues(java.lang.String

name)在構(gòu)造響應(yīng)消息數(shù)據(jù)時,通常需要建立PrintWriter類型對象的輸出流,向該流中寫數(shù)據(jù)。在每個Servlet文件編輯完成之后,還需要在Servlet注冊管理文件web.xml中注冊每個Servlet,這樣Web應(yīng)用程序才能尋找到Servlet的代碼,進而調(diào)用其方法。

Servlet由容器調(diào)用執(zhí)行,容器根據(jù)web.xml配置文件來定位和裝載Servlet的代碼,進而生成該類的實例。

Servlet的實現(xiàn)步驟是:

(1)通過編輯web.xml注冊Servlet。主要修改web.xml中的<servlet>…</servlet>和<servlet-mapping>…</servlet-mapping>這兩個數(shù)據(jù)項中的內(nèi)容。

<servlet>數(shù)據(jù)項中有很多數(shù)據(jù)子項,一般最常用的是<servlet-name>和<servlet-class>數(shù)據(jù)項,這兩個數(shù)據(jù)項用來定義Servlet的名稱和Servlet的類代碼。<servlet-mapping>中的兩個數(shù)據(jù)子項為<servlet-name>和<url-pattern>,其中<servlet-name>數(shù)據(jù)項對應(yīng)<servlet><servlet-name>中的數(shù)據(jù)項,<url-pattern>為該Servlet被訪問時的URL定義。

當(dāng)使用Eclipse+Lomboz插件開發(fā)的時候,以上4個數(shù)據(jù)項的內(nèi)容會由模板自動生成,開發(fā)人員可以查看、編輯修改web.xml文件的內(nèi)容。

(2)客戶端去請求該Servlet,觸發(fā)容器調(diào)用Servlet。7.7ServletAPI常用接口和類

JavaServletAPI是一組接口和類,以包的形式提供給開發(fā)人員使用。JavaServletAPI提供了兩個包:

(1)?javax.servlet包。該包實現(xiàn)了未定義通信協(xié)議的Servlet接口和類。

(2)?javax.servlet.http包。該包實現(xiàn)了使用HTTP協(xié)議通信的Servlet接口和類。

API的詳細(xì)說明文檔如表7.2所示。讀者可以到Sun公司網(wǎng)站查閱和下載,網(wǎng)址為/products/servlet/2.5/docs/servlet-2_5-mr2/index.html。

ServletAPI接口和類一覽表如表7.3所示。最常用的接口是Servlet、ServletConfig、ServletRequest、ServletResponse、HttpServletRequest、HttpServletResponse、HttpSession,其中HttpServletRequest繼承ServletRequest,HttpServletResponse繼承ServletResponse。最常用的類是GenericServlet、HttpServlet以及異常類ServletException、UnavailableException。這些常用接口和類提供了創(chuàng)建Servlet、創(chuàng)建請求消息和響應(yīng)消息對象的類型。

Servlet接口的常用方法如下:

voiddestroy()

ServletConfiggetServletConfig()

java.lang.StringgetServletInfo()

voidinit(ServletConfigconfig)

voidservice(ServletRequsetreq,ServletResponseres)

關(guān)于方法的說明請參考相關(guān)文檔。

GenericServlet類是一個抽象類,它實現(xiàn)了Servlet接口,具有Servlet的所有方法。該類的聲明為:

publicabstractclassGenericServlet

extendsjava.lang.Object

implementsServlet,ServletConfig,java.io.Serializable

該類最重要的抽象方法是:

abstractvoidservice(ServletRequestreq,ServletResponseres)

繼承該類,必須實現(xiàn)該抽象方法。該抽象方法的兩個最重要的參數(shù)是req和res,實參由Servlet容器傳入,該方法負(fù)責(zé)修改實參對象數(shù)據(jù),通過res參數(shù)將處理結(jié)果傳回Servlet容器。

GenericServlet類的常用方法如下:

java.lang.String getInitParameter(java.lang.String

name)

java.util.Enumeration getInitParameterNames()

ServletConfig getServletConfig()

ServletContext getServletContext()

java.lang.String getServletInfo()

java.lang.String getServletName()

void init()

void init(ServletConfig

config)

abstract

void service(ServletRequest

req,ServletResponse

res)

HttpServlet類是設(shè)計和開發(fā)Servlet的人員直接繼承的最常用的頂層Servlet,該類繼承了GenericServlet類。如果Servlet類繼承了HttpServlet類,通常不直接實現(xiàn)service方法,因為該類已經(jīng)實現(xiàn)了service方法。在service方法中,根據(jù)不同的請求方式調(diào)用不同的方法,開發(fā)人員主要實現(xiàn)這些不同的請求處理方法。

請求處理方法和請求類型的對應(yīng)關(guān)系如表7.5所示。7.8Servlet應(yīng)用實例

【例7.7】實現(xiàn)一個向客戶端輸出簡單文本的Servlet。

分析:該Servlet不需要分析請求消息數(shù)據(jù),只需要構(gòu)造一個響應(yīng)消息數(shù)據(jù),向響應(yīng)消息輸出流寫入數(shù)據(jù),即可向客戶端輸出簡單文本。

操作:先建立代碼框架,然后實現(xiàn)方法,并在web.xml中注冊。

在Eclipse環(huán)境中的操作步驟如下:

(1)在前面建立的工程中添加Servlet,在工程視圖欄(ProjectExplorer)的目錄中選定存放Servlet源代碼的目錄(JavaResources:src),如圖7.20所示。圖7.20選定存放Servlet源代碼目錄的界面

(2)在該目錄下添加一個Servlet。選中JavaResources:src目錄,單擊鼠標(biāo)右鍵,彈出【New】菜單,在【New】菜單下選擇【Other…】,如圖7.21所示。圖7.21選擇添加Servlet

(3)在彈出的如圖7.22所示界面中添加Web項內(nèi)容,選擇【W(wǎng)eb】下的【Servlet】。圖7.22選擇Web的子項Servlet

(4)定制Servlet的名稱(Classname),定義或者選擇包名(在Javapackage項后的文本框中填寫),如圖7.23所示。填好后單擊【Next】按鈕。圖7.23定制Servlet名稱和存儲目錄

(5)在出現(xiàn)的如圖7.24所示界面中,定制web.xml中關(guān)于Servlet的配置項。如果不定義初始參數(shù),可以選擇默認(rèn),直接單擊【Next】按鈕。圖7.24定制web.xml中關(guān)于該Servlet的配置項

(6)定制Servlet的修飾符及方法。一般選擇不作任何改動。單擊【Finish】按鈕,完成Servlet源代碼模板的創(chuàng)建,如圖7.25所示。圖7.25定制Servlet的方法和修飾符

(7)單擊【Finish】按鈕后,生成Servlet源代碼框架模板和web.xml配置文件。在此文件中添加處理代碼,最后的結(jié)果如下:

①??HelloWorld.java文件:

packageservlet.web;

importjava.io.IOException;

importjava.io.PrintWriter;//輸出字符流,用來寫文本

importjavax.servlet.ServletException;

importjavax.servlet.http.HttpServletRequest;

//請求消息信息類,請求消息對象的類型,請求消息被作為doXXX的參數(shù)之一

importjavax.servlet.http.HttpServletResponse;

//響應(yīng)消息信息類,響應(yīng)消息對象的類型,響應(yīng)消息被作為doXXX的參數(shù)之一

publicclassHelloWorldextendsjavax.servlet.http.HttpServletimplementsjavax.servlet.Servlet{

publicHelloWorld(){

super();

}

//一般只修改此方法即可,此方法的功能是分析請求消息數(shù)據(jù),構(gòu)造響應(yīng)消息數(shù)據(jù)。

//對該題不需要分析請求消息數(shù)據(jù),只需要構(gòu)造響應(yīng)消息 protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{

//該題只構(gòu)造響應(yīng)消息

response.setContentType("text/html;charset=gb2312");

//用來設(shè)置響應(yīng)消息的MIME類型:此處為text/html,客戶端將該響應(yīng)消息的

//正文(Body)數(shù)據(jù)按text/html格式解析。字符集編碼方式為gb2312

PrintWriterout=response.getWriter();

//創(chuàng)建字符輸出流對象,該字符輸出流可以把任意類型的數(shù)據(jù)按字符的方式寫入

//這樣響應(yīng)消息正文(Body)中的數(shù)據(jù)都按文本的方式對待。注意此處的out對象為

//PrintWriter類型的對象的引用名,可以用其他名稱代替,不是System.out中

//的System數(shù)據(jù)成員out,不要混淆。程序員只需要向響應(yīng)消息提供的這個流對象

//中寫數(shù)據(jù)即可,最后流中的數(shù)據(jù)是被服務(wù)器以響應(yīng)消息的形式發(fā)往客戶端瀏覽器,

//最終被瀏覽器軟件解析并顯示出來的

//以下用來構(gòu)造響應(yīng)消息正文,即向流對象中寫入一個簡單文本。這部分需要熟悉

//html各標(biāo)簽的含義及頁面的寫法

out.println(“<html>”);

out.println(“<head><title>HelloWorld</title></head>”);

out.println(“<bodybgcolor=\”FFFFFF\“>”);

out.println(“<center><H1>HelloWorld!

</H1></center>");

out.println("</body>"); out.println(“</html>”);

}

protectedvoiddoPost(HttpServletRequestrequest,

HttpServletResponseresponse)throwsServletException,

IOException{

}

}

②?web.xml文件:

<?xmlversion=“1.0”encoding=“UTF-8”?>

<web-appid=“WebApp_ID”version=“2.4”

xmlns="/xml/ns/j2ee"

xmlns:xsi=/2001/XMLSchema-instance

xsi:schemaLocation=“/xml/ns/j2ee

/xml/ns/j2ee/web-app_2_4.xsd”>

<display-name>WebExample</display-name>

<servlet>

<description></description>

<display-name>HelloWorld</display-name>

<servlet-name>HelloWorld</servlet-name>

<servlet-class>servlet.web.HelloWorld</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>HelloWorld</servlet-name>

<url-pattern>/HelloWorld</url-pattern>

</servlet-mapping>

<welcome-file-list>

<welcome-file>index.html</welcome-file>

<welcome-file>index.htm</welcome-file>

<welcome-file>index.jsp</welcome-file>

<welcome-file>default.html</welcome-file>

<welcome-file>default.htm</welcome-file>

<welcome-file>default.jsp</welcome-file>

</welcome-file-list>

</web-app>

該web.xml文件從<servlet>開始到</servlet-mapping>部分屬于Servlet配置項內(nèi)容。

(8)運行該Servlet。在Porject視圖欄中選中該Servlet,單擊鼠標(biāo)右鍵,選擇在服務(wù)器上運行,如圖7.26所示。圖7.26運行Servlet

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論