




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第6章系統(tǒng)流程控制
6.1Servlet6.2使用Servlet完成控制
6.3使用MVC模式
6.4信息存儲(chǔ)
小結(jié)
習(xí)題6實(shí)訓(xùn)6:編寫(xiě)圖書(shū)信息添加Servlet 6.1Servlet
6.1.1什么是Servlet
從完成的功能上來(lái)說(shuō),Servlet與JSP完全一樣。但是,從編寫(xiě)的角度來(lái)說(shuō)是不一樣的:JSP是在HTML或者XML文檔中嵌入Java腳本或者JSP標(biāo)簽形成的,是文本文件;而Servlet是純Java文件,是一個(gè)類。所有使用Servlet完成的功能,包括與用戶的交互,都是通過(guò)Java代碼完成的。
Servlet是用Java語(yǔ)言編寫(xiě)的運(yùn)行在服務(wù)器端的小應(yīng)用程序,能夠接收Web客戶端的請(qǐng)求,并能對(duì)Web客戶端進(jìn)行響應(yīng),通常是通過(guò)HTTP(HyperTextTransferProtocol)協(xié)議進(jìn)行工作的。
可以認(rèn)為Servlet是服務(wù)器端的Applet(實(shí)際上,Applet運(yùn)行在客戶端,而Servlet運(yùn)行在服務(wù)器端)。6.1.2Servlet的主要方法
Servlet是一個(gè)Java類,通常會(huì)有三類方法,分別是:
(1)
init方法,用于初始化。
(2)
destroy方法,用于釋放資源。
(3)
service方法(服務(wù)類方法),對(duì)用戶的請(qǐng)求進(jìn)行處理,并對(duì)用戶進(jìn)行響應(yīng)。幾乎所有處理功能都在這里完成。這類方法可以有多個(gè),例如doGet和doPost等。doGet方法可以響應(yīng)get方式的請(qǐng)求,doPost方法可以響應(yīng)post方式的請(qǐng)求。通常,表單提交都使用post方式,超鏈接使用get方式。
6.1.3編寫(xiě)簡(jiǎn)單的Servlet
1.編寫(xiě)Servlet
根據(jù)要完成的功能來(lái)編寫(xiě)Servlet。功能確定之后,根據(jù)Servlet的框架來(lái)編寫(xiě)Servlet。這里主要關(guān)注編寫(xiě)Servlet的一般過(guò)程。
因?yàn)镾ervlet是Java類,所以它與一般的Java類的編寫(xiě)基本相同。具體步驟如下:
(1)創(chuàng)建一個(gè)包。假設(shè)包名是servlets,創(chuàng)建包的代碼如下:
packageservlets;
(2)導(dǎo)入用到的包。需要導(dǎo)入的包有javax.servlet.*和javax.servlet.http.*,通常還需要導(dǎo)入的包是java.io.*。代碼如下:
importjavax.servlet.*;
importjavax.servlet.http.*;
importjava.io.*;
(3)定義類的基本框架并繼承HttpServlet。每個(gè)Servlet都必須實(shí)現(xiàn)接口Servlet,而這里要編寫(xiě)的Servlet主要是用于HTTP協(xié)議的,可以繼承實(shí)現(xiàn)了Servlet接口的HttpServlet。代碼如下:
publicclassHelloServletextendsHttpServlet
{
}
(4)編寫(xiě)成員方法。Servlet通常不需要成員變量,成員方法包括init、service、destroy等。如果需要對(duì)Servlet進(jìn)行初始化,則需要實(shí)現(xiàn)init方法。如果需要在卸載Servlet的時(shí)候執(zhí)行一些功能,則需實(shí)現(xiàn)destory方法。一般情況下,根據(jù)需要完成的功能只需要實(shí)現(xiàn)服務(wù)類方法即可。這里只實(shí)現(xiàn)doGet方法。服務(wù)類方法有兩個(gè)參數(shù):第一個(gè)參數(shù)是HttpServletRequest的對(duì)象,該參數(shù)包含了用戶的所有請(qǐng)求信息,要想獲取用戶的請(qǐng)求信息,必須使用該對(duì)象提供的方法;第二個(gè)參數(shù)是HttpServletResponse的對(duì)象,可以通過(guò)這個(gè)對(duì)象對(duì)用戶進(jìn)行響應(yīng),如果希望對(duì)用戶進(jìn)行響應(yīng)或者設(shè)置響應(yīng)相關(guān)的信息,需要使用該對(duì)象的方法。
該實(shí)例完成的功能是向用戶輸出一行文字,所以不需要獲取用戶的請(qǐng)求信息,只需要對(duì)用戶進(jìn)行響應(yīng)即可。在對(duì)用戶進(jìn)行響應(yīng)的時(shí)候,需要設(shè)定文檔類型以及編碼方式等,就像在JSP中每個(gè)文件都要設(shè)置page標(biāo)簽的contentType屬性一樣。之后要向用戶輸出一些內(nèi)容,需要先獲取輸出流。響應(yīng)頁(yè)面的屬性設(shè)置和輸出流的獲取都是與響應(yīng)相關(guān)的,需要使用第二個(gè)參數(shù)來(lái)完成。
代碼如下:
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponse)
throwsIOException,ServletException
{
response.setContentType("text/html;charset=gb2312");
PrintWriterout=response.getWriter();
out.println("<html>");
out.println("<head><title>HelloWorld!</title></head>");
out.println("<body>");
out.println("<p>HelloWorld!</p>");
out.println("</body></html>");
}從代碼可以看出,如果使用Servlet完成對(duì)用戶的響應(yīng),所有的響應(yīng)內(nèi)容,包括格式信息等都要通過(guò)輸出語(yǔ)句進(jìn)行輸出。要是使用JSP完成這個(gè)功能,就非常簡(jiǎn)單了。正因?yàn)檫@個(gè)原因,才推出了JSP技術(shù),JSP技術(shù)的主要優(yōu)勢(shì)就在于與用戶進(jìn)行交互比較方便。所以,如果要完成的功能是與用戶進(jìn)行交互,則應(yīng)該使用JSP完成。在本書(shū)的后續(xù)內(nèi)容中,使用Servlet技術(shù)主要完成控制功能。
為了使這個(gè)Servlet能夠響應(yīng)post請(qǐng)求,需要實(shí)現(xiàn)doPost方法,這時(shí)只需要調(diào)用doGet方法即可。代碼如下:
publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
doGet(request,response);
}
需要把這兩個(gè)方法添加到前面定義的類HelloServlet中。
2.編譯Servlet
Servlet開(kāi)發(fā)所需要的包有javax.servlet.*和javax.servlet.http.*。這些包不是Java標(biāo)準(zhǔn)版的類庫(kù),如果沒(méi)有安裝JavaEE開(kāi)發(fā)環(huán)境,則需要配置環(huán)境變量。這些包位于tomcat安裝目錄下的lib下的servlet-api.jar壓縮包中,需要把這個(gè)壓縮包添加到環(huán)境變量中。
假設(shè)servlet-api.jar所在的位置為C:\ProgramFiles\ApacheSoftwareFoundation\Tomcat6.0\lib,需要在環(huán)境變量classpath中添加C:\ProgramFiles\ApacheSoftwareFoundation\Tomcat6.0\lib\servlet-api.jar。
3.配置Servlet
Servlet編寫(xiě)完之后,作為Web應(yīng)用的組成部分,需要在配置文件web.xml中進(jìn)行配置。Servlet的配置包括兩部分,第一部分是Servlet的聲明,第二部分是Servlet訪問(wèn)方式的設(shè)置。
首先是Servlet的聲明,使用<servlet>元素:
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>servlets.HelloServlet</servlet-class>
</servlet>
<servlet-name>用于聲明Servlet的名字,這里,hello是Servlet的名字;<servlet-class>用于聲明Servlet所對(duì)應(yīng)的類,這里,servlets.HelloServlet是這個(gè)Servlet所對(duì)應(yīng)的類名。
然后是Servlet映射,主要配置訪問(wèn)該Servlet的方式,使用<servlet-mapping>元素:
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-name>表示Servlet的名字,需要和上面的Servlet聲明保持一致;<url-pattern>表示訪問(wèn)時(shí)候的格式,例如要訪問(wèn)上面這個(gè)Servlet需要使用hello作為名字訪問(wèn)。servlet-name和url-pattern可以不相同。服務(wù)器接收到請(qǐng)求之后會(huì)根據(jù)這個(gè)url-pattern查找相應(yīng)的Servlet。
4.部署Servlet
Servlet編寫(xiě)完成之后,需要部署到服務(wù)器才能訪問(wèn),編譯好的文件需要放在Web應(yīng)用的WEB-INF\classes下面。
5.訪問(wèn)Servlet
對(duì)Servlet的訪問(wèn)與對(duì)JSP的訪問(wèn)基本相同,可以通過(guò)以下三種方式進(jìn)行:
(1)通過(guò)在瀏覽器中直接輸入地址訪問(wèn):
:8080/test/hello
(2)通過(guò)超鏈接的形式訪問(wèn):
<ahref=":8080/test/hello">第一個(gè)Servlet</a>
(3)通過(guò)表單提交的方式訪問(wèn):
<formmethod=getaction=":8080/test/hello">6.1.4Servlet運(yùn)行原理
圖6.1顯示了Servlet的運(yùn)行原理:
(1)服務(wù)器接收到客戶端的請(qǐng)求時(shí),先判斷用戶所請(qǐng)求的Servlet對(duì)象是否存在:
●如果存在,則直接調(diào)用Servlet對(duì)象的Service方法(間接調(diào)用doGet方法或者doPost方法);
●如果不存在,則加載Servlet類,創(chuàng)建Servlet對(duì)象并實(shí)例化,然后調(diào)用init方法進(jìn)行初始化,之后調(diào)用Servlet對(duì)象的Service方法。
(2)使用service方法執(zhí)行的結(jié)果對(duì)用戶進(jìn)行響應(yīng)。
圖6.1Servlet的運(yùn)行原理
在Web應(yīng)用被卸載或者服務(wù)器被關(guān)閉的時(shí)候,系統(tǒng)卸載Servlet,調(diào)用destroy方法釋放資源。
Servlet的加載有兩種方式:
●第一次請(qǐng)求的時(shí)候加載。
●服務(wù)器啟動(dòng)的時(shí)候加載。
這兩種方式各有利弊。如果第一次請(qǐng)求的時(shí)候加載,加載的速度比較慢,但是不浪費(fèi)空間。如果是啟動(dòng)服務(wù)器的時(shí)候加載,第一次訪問(wèn)的時(shí)候就快了,但是如果一直沒(méi)有人訪問(wèn),則這段時(shí)間就浪費(fèi)了空間。
加載Servlet的方式可以在web.xml中聲明Servlet的時(shí)候配置。如果希望在啟動(dòng)的時(shí)候加載HelloServlet,可使用下面的代碼聲明:
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>servlets.HelloServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet> 6.2使用Servlet完成控制
6.2.1接收用戶的輸入信息
在Servlet中,doPost和doGet服務(wù)方法中都有一個(gè)參數(shù)是HttpServletRequest的對(duì)象,用戶的請(qǐng)求信息存放在該對(duì)象中,要獲取用戶提交的數(shù)據(jù)需要通過(guò)該對(duì)象獲取。獲取用戶請(qǐng)求信息的方法如下:
StringgetParameter(Stringname)
String[]getParamterValues(Stringname)第一個(gè)方法用于獲取單值表單元素的值,參數(shù)指出要獲取的表單元素的名字。例如,用戶在輸入用戶編號(hào)的時(shí)候使用的表單元素的名字是userid,要想獲取用戶在這個(gè)輸入框中輸入的值,就可以使用下面的代碼:
Stringuserid=request.getParameter("userid");
如果參數(shù)指定的表單元素的名字不存在,則返回null。所以通常在處理的時(shí)候,需要先判斷返回的結(jié)果是否為null。
第二個(gè)方法用于獲取多值表單元素的值,參數(shù)也是表單元素的名字,但是返回值是一個(gè)數(shù)組。
6.2.2調(diào)用業(yè)務(wù)方法
因?yàn)镾ervlet是Java類,所以調(diào)用業(yè)務(wù)方法的代碼就是我們?cè)贘ava中學(xué)習(xí)的調(diào)用其他類的方法。首先需要?jiǎng)?chuàng)建所使用的JavaBean的對(duì)象,然后再調(diào)用業(yè)務(wù)方法。
要使用UserBean對(duì)象,可以使用下面的代碼:
UserBeanuser=newUserBean();
然后調(diào)用業(yè)務(wù)方法,代碼如下:
booleanb=user.validate(userid,userpass);6.2.3使用request存儲(chǔ)執(zhí)行的結(jié)果
Servlet完成控制的功能,查詢的結(jié)果通過(guò)視圖(JSP文件)顯示,需要把查詢的結(jié)果傳遞給JSP文件。因?yàn)榇蜷_(kāi)這兩個(gè)文件屬于同一次請(qǐng)求,所以共享同一個(gè)request。因?yàn)楣蚕硗粋€(gè)request,所以在Servlet中把查詢結(jié)果存儲(chǔ)在request中,然后在視圖中顯示結(jié)果。
在登錄功能中不需要傳遞信息。假設(shè)需要把使用temp對(duì)象保存的查詢結(jié)果傳遞到視圖,可以使用下面的代碼:
request.setAttribute("user",temp);6.2.4選擇界面對(duì)用戶進(jìn)行響應(yīng)
Servlet中的最后一項(xiàng)任務(wù)就是跳轉(zhuǎn)到顯示界面,在顯示界面顯示信息。在JSP中要重定向到某個(gè)文件,可以使用<jsp:forward>標(biāo)簽。那么在Servlet中如何完成這種跳轉(zhuǎn)呢?在Servlet中提供了一個(gè)RequestDispatcher接口,通過(guò)這個(gè)接口可以完成重定向功能。
要使用RequestDispatcher,需要先創(chuàng)建該類的對(duì)象,可以通過(guò)request的getRequestDispatcher方法創(chuàng)建。該方法需要一個(gè)String類型的參數(shù),該參數(shù)指定要轉(zhuǎn)向的文件。假設(shè)要轉(zhuǎn)向userlist.jsp,可以使用下面的代碼:
RequestDispatcherrd=request.getRequestDispatcher("userlist.jsp");要完成轉(zhuǎn)向,還需要調(diào)用一個(gè)方法,用法如下:
rd.forward(request,response);
在學(xué)習(xí)<jsp:forward>標(biāo)簽的時(shí)候,還學(xué)習(xí)過(guò)一個(gè)標(biāo)簽<jsp:include>。<jsp:include>標(biāo)簽對(duì)應(yīng)的功能在Servlet中的實(shí)現(xiàn)也是通過(guò)上面的RequestDispatcher來(lái)實(shí)現(xiàn)的。例如現(xiàn)在要包含userlist.jsp,而不是轉(zhuǎn)向success.jsp,可以使用下面的代碼:
RequestDispatcherrd=request.getRequestDispatcher("success.jsp");
rd.include(request,response);實(shí)際上,還有一個(gè)方法,即response對(duì)象的sendRedirect方法可以完成重定向的功能。例如要轉(zhuǎn)向success.jsp,可以使用下面的代碼:
response.sendRedirect("success.jsp");
但是對(duì)于我們當(dāng)前的功能來(lái)說(shuō),不能使用這個(gè)方法,因?yàn)檫@個(gè)方法與上面介紹的方法有一些區(qū)別。在使用RequestDispatcher的時(shí)候,當(dāng)前文件和要轉(zhuǎn)向的文件屬于同一次請(qǐng)求,可以共享request對(duì)象。而在使用response對(duì)象的sendRedirect方法的時(shí)候,當(dāng)前文件和要轉(zhuǎn)向的文件不屬于同一次請(qǐng)求,屬于兩次請(qǐng)求,所以不能共享request。如果需要通過(guò)request對(duì)象傳遞信息,就不能使用response的sendRedirect方法。如果當(dāng)前文件和要轉(zhuǎn)向的文件不需要共享任何信息,那么這時(shí)候兩種方式都可以。
6.2.5完整的代碼
完整的代碼如下:
packageservlets;
importjavax.servlet.*;
importjavax.servlet.http.*;
importjava.io.*;
importbeans.*;
publicclassLoginServletextendsHttpServlet{
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsIOException,ServletException{
//獲取用戶輸入的用戶ID和口令
Stringuserid=request.getParameter("userid");
Stringuserpass=request.getPrameter("userpass");
//創(chuàng)建模型對(duì)象
UserBeanuser=newUserBean();
//調(diào)用業(yè)務(wù)方法進(jìn)行驗(yàn)證
booleanb=user.validate(userid,userpass);
//要轉(zhuǎn)向的文件
Stringforward;
//如果登錄成功,就把用戶名寫(xiě)入session中,并且轉(zhuǎn)向success.jsp,
//否則轉(zhuǎn)向failure.jsp
if(b){
//目標(biāo)轉(zhuǎn)向文件是success.jsp
forward="success.jsp";
}else{
//目標(biāo)轉(zhuǎn)向文件是failure.jsp
forward="failure.jsp";
}
//獲取Dispatcher對(duì)象
RequestDispatcherdispatcher=request.getRequestDispatcher(forward);
//完成跳轉(zhuǎn)
dispatcher.forward(request,response);
}
}
LoginServlet編寫(xiě)完之后需要配置。在web.xml中配置如下:
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>servlets.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
要在login.jsp中訪問(wèn)Servlet,需要修改form表單中的action屬性,修改如下:
<formname="form1"action="login"method="post"
onsubmit="returnisValidate(form1)">
6.3使用MVC模式
MVC模式是一種軟件開(kāi)發(fā)模式。
M是Model的縮寫(xiě),表示模型,主要完成系統(tǒng)的邏輯處理。V是View的縮寫(xiě),表示視圖,主要完成與用戶的交互。C是Controller的縮寫(xiě),表示控制器,主要用來(lái)建立模型與視圖之間的關(guān)聯(lián)。
6.3.1分層
在MVC模式中,每個(gè)功能都被分成三個(gè)部分,或者稱為三層。例如,登錄功能可以分成三個(gè)部分。
第一部分稱為視圖,是與人進(jìn)行交互的部分,包括登錄界面和登錄處理之后的界面(或者是登錄成功界面,或者是登錄失敗界面)。登錄界面是供用戶輸入信息的,如果登錄成功會(huì)顯示登錄成功界面,如果登錄失敗會(huì)顯示登錄失敗界面。
因?yàn)橐晥D部分主要是用來(lái)與人進(jìn)行交互的,包括輸入和輸出界面,所以在JavaWeb開(kāi)發(fā)技術(shù)中,使用JSP文件作為視圖。在本章示例中,登錄界面是login.jsp,登錄成功的界面是success.jsp,登錄失敗的界面是failure.jsp。
第二部分稱為模型,是處理功能部分,用于登錄的處理以及判斷用戶提交的信息是否有效、用戶名是否存在、口令是否正確。
根據(jù)前面的學(xué)習(xí),JavaBean主要用于業(yè)務(wù)邏輯的處理,所以在模型層通常使用JavaBean,也可以使用EJB(企業(yè)級(jí)的JavaBean,不屬于本書(shū)的討論范圍,如果讀者感興趣,可以參考相關(guān)資料)。在本章示例中使用UserBean完成處理。
第三部分稱為控制器,用來(lái)接收用戶輸入的用戶名和口令,然后調(diào)用處理功能,返回處理的結(jié)果,根據(jù)處理的結(jié)果選擇界面對(duì)用戶響應(yīng)。如果返回的信息表示登錄成功,則給用戶顯示登錄成功的界面。如果返回的信息表示登錄失敗,則給用戶顯示登錄失敗的界面。
圖6.2MVC模式關(guān)系圖
6.3.2傳值
傳值包括兩個(gè)方面:視圖層與控制層之間值的傳遞;控制層與模型層之間值的傳遞。視圖層與模型層之間不直接交互,所以不需要在這兩層之間傳遞值。
1.視圖層與控制層之間值的傳遞
視圖層與控制層之間值的傳遞包括兩個(gè)方向:
●從視圖層到控制層;
●從控制層到視圖層。
對(duì)于從視圖層到控制層之間值的傳遞,可以在視圖層通過(guò)表單或者采用在請(qǐng)求字符串之后使用問(wèn)號(hào)加參數(shù)的方式(例如,:8080/bookstore/login?userid=zhangsan
&userpass=lisi)來(lái)實(shí)現(xiàn)。這兩種方式都可以把信息傳遞到服務(wù)器,都會(huì)被服務(wù)器封裝到request對(duì)象中。
控制層要獲取這些信息,可以通過(guò)request的getParameter方法和getParameterValues方法來(lái)實(shí)取。
從控制層到視圖層傳遞信息,也是使用request對(duì)象。信息通常都會(huì)封裝成對(duì)象,如果是多個(gè)對(duì)象,則需要封裝成一個(gè)集合(Vector對(duì)象或者ArrayList對(duì)象)。在控制層需要做的工作是:把信息保存到request中。例如,要把用戶信息user保存到request中,可以使用下面的代碼:
request.setAttribute("user",user);其中,第一個(gè)參數(shù)是保存的信息的名字,第二個(gè)參數(shù)是要保存的對(duì)象本身。要保存的對(duì)象可以是任意類型的對(duì)象,但是不能保存基本數(shù)據(jù)類型定義的變量。如果要傳遞基本數(shù)據(jù)類型的變量,可以把它們封裝成相應(yīng)的封裝類,例如把int變量封裝成Integer對(duì)象,把char變量封裝成Character對(duì)象。
在視圖層要獲取控制層保存的信息,可以使用表達(dá)式語(yǔ)言。如果要傳遞的信息本身是對(duì)象,可以直接使用表達(dá)式語(yǔ)言進(jìn)行輸出。例如前面?zhèn)鬟f的user對(duì)象,可以使用表達(dá)式語(yǔ)言輸出它的屬性:
姓名:${user.username}密碼:${user.userpass}如果是集合對(duì)象,需要使用循環(huán)進(jìn)行處理,可以使用標(biāo)準(zhǔn)標(biāo)簽庫(kù)中的<c:forEach>標(biāo)簽,假設(shè)從控制層傳遞過(guò)來(lái)的是用戶的集合,變量的名字是list,則可以使用下面的代碼輸出所有用戶的信息:
<table>
<tr><th>用戶名</th><th>口令</th></tr>
<c:forEachvar="user"items="${list}">
<tr>
<td>${user.username}</td>
<td>${user.userpass}</td>
</tr>
</c:forEach>
</table>
2.控制層與模型層之間值的傳遞
從控制層向模型層傳遞信息,通??梢圆捎孟旅娴?種方式之一:
●在調(diào)用構(gòu)造方法的時(shí)候傳遞;
●調(diào)用專門(mén)的初始化方法賦值或者通過(guò)調(diào)用setter方法賦值;
●通過(guò)業(yè)務(wù)方法的參數(shù)傳遞。
從模型層向控制層傳遞信息,通常都是通過(guò)方法的返回值實(shí)現(xiàn)的。運(yùn)行過(guò)程中的異常信息通過(guò)異常處理傳遞。
6.3.3MVC模式在JavaWeb中的應(yīng)用
流行的JavaWeb應(yīng)用框架基本上都實(shí)現(xiàn)了MVC模式。下面分別以JSF和Struts為例,介紹這些框架是如何實(shí)現(xiàn)MVC模式的。
1.JSF
在JSF框架中提供了一個(gè)中心控制器FacesServlet以完成所有的控制,這樣所有的請(qǐng)求都可以提交給這個(gè)Servlet。此時(shí)需要在web.xml中進(jìn)行配置,典型的代碼如下:
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>在代碼中,url-pattern的值是“*.faces”,意味著所有的以.faces結(jié)束的請(qǐng)求都會(huì)由中心控制器FacesServlet處理。
另外在使用JSF框架的時(shí)候還需要編寫(xiě)一個(gè)配置文件。在上面的配置中可以看到有一個(gè)參數(shù)指向了一個(gè)配置文件faces-config.xml,這個(gè)文件是所有的JSF應(yīng)用中必須提供的。在這個(gè)配置文件中可以描述文件之間的跳轉(zhuǎn)關(guān)系以及所使用的JavaBean等。下面是某個(gè)應(yīng)用中的faces-config.xml中的部分代碼:
<navigation-rule>
<from-view-id>/login.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/ok.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/error.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<managed-bean>
<managed-bean-name>userValidator</managed-bean-name>
<managed-bean-class>validator.UserValidator</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>其中,<navigation-rule>表示一個(gè)跳轉(zhuǎn)關(guān)系,<from-view-id>表示從哪個(gè)頁(yè)面發(fā)送的請(qǐng)求,<navigation-case>表示一個(gè)可能的跳轉(zhuǎn),<from-outcome>表示一種情況的條件,<to-view-id>表示這種條件下的跳轉(zhuǎn)目標(biāo),<managed-bean>表示一個(gè)被容器自動(dòng)加載的類,所以所有的JavaBean基本上都不需要實(shí)例化。
在JSF框架中,模型部分也是采用JavaBean實(shí)現(xiàn)的,這與前面介紹的基本的MVC部分沒(méi)有區(qū)別。
JSF框架中的視圖部分仍然使用JSP文件實(shí)現(xiàn),這樣做只是為了與框架更好地結(jié)合。JSF提供了大量的自定義標(biāo)簽庫(kù)來(lái)增強(qiáng)頁(yè)面的功能。
在值的傳遞方面,JSF提供了表達(dá)式語(yǔ)言。通過(guò)表達(dá)式語(yǔ)言,可以直接把值從視圖層傳遞到模型層,也可以把值從模型層傳遞到視圖層。當(dāng)然具體的傳遞過(guò)程仍然是通過(guò)控制層完成的。這相當(dāng)于把前面介紹的多種值的傳遞結(jié)合在一起了。
2.Struts
在Struts中提供了一個(gè)中心控制器ActionServlet來(lái)完成所有的控制,這樣所有的請(qǐng)求都可以提交給這個(gè)Servlet。它也需要在web.xml中進(jìn)行配置,典型的代碼如下:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>在代碼中,url-pattern的值是“*.do”,意味著所有的以.do結(jié)束的請(qǐng)求都會(huì)由中心控制器ActionServlet處理。對(duì)應(yīng)用戶的每個(gè)請(qǐng)求,都需要編寫(xiě)一個(gè)Action,與中心控制器一起完成控制功能。Action控制器中的代碼與現(xiàn)在介紹的控制器中的代碼基本相同。
另外,在使用Struts框架的時(shí)候還需要編寫(xiě)一個(gè)配置文件。在上面的配置中可以看到有一個(gè)參數(shù)指向了一個(gè)配置文件struts-config.xml,這個(gè)文件是所有的Struts應(yīng)用中必須提供的,在這個(gè)配置文件中可以描述文件之間的跳轉(zhuǎn)關(guān)系,以及請(qǐng)求路徑和處理文件之間的關(guān)系。下面是某個(gè)應(yīng)用的struts-config.xml中的部分代碼:
<struts-config>
<action-mappings>
<actionpath="/findAction"type="com.li.action.FindAction">
<forwardname="success"path="/test.jsp"/>
</action>
</action-mappings>
<message-resourcesparameter="ApplicationResources"/>
</struts-config>其中,每個(gè)action元素就表示一個(gè)請(qǐng)求,path屬性指出請(qǐng)求的名字,例子中的名字對(duì)應(yīng)一個(gè)以findAction.do結(jié)束的請(qǐng)求;type指出該請(qǐng)求由哪個(gè)Action處理,com.li.cation.FindAction就是要與中心控制器協(xié)同工作的Action;子元素<forward>表示Action執(zhí)行完之后可能跳轉(zhuǎn)到什么文件,這里的配置表明如果用戶在程序中選擇了success,最后將跳轉(zhuǎn)到test.jsp文件;后面的<message-resources>元素表示應(yīng)用所使用的資源文件。
Struts中的模型部分與本書(shū)中介紹的模型沒(méi)有區(qū)別。
Struts中的視圖部分仍然使用JSP文件實(shí)現(xiàn),但是Struts提供了大量的自定義標(biāo)簽庫(kù)來(lái)增強(qiáng)頁(yè)面的功能。
6.3.4如何實(shí)現(xiàn)MVC模式
采用MVC模式,所有問(wèn)題的考慮方式基本相同,都分下面三步進(jìn)行:
(1)任何一個(gè)功能都是先從用戶的角度考慮,考慮假設(shè)這個(gè)功能寫(xiě)完了,用戶如何使用它。通常需要考慮兩個(gè)方面,即用戶如何提交請(qǐng)求和系統(tǒng)如何向用戶展示結(jié)果,這可以理解為通常意義上的輸入和輸出。輸入和輸出主要使用JSP頁(yè)面來(lái)完成,可以根據(jù)輸入和輸出功能所涉及的元素設(shè)計(jì)JSP頁(yè)面。這就是MVC模式中V部分的設(shè)計(jì)。
(2)考慮功能如何實(shí)現(xiàn),所有的功能最后都是通過(guò)方法來(lái)實(shí)現(xiàn)的。考慮兩個(gè)方面:首先考慮這個(gè)方法屬于已經(jīng)存在的某個(gè)模型的方法,還是不屬于任何已經(jīng)存在的模型的方法。對(duì)于前者,只需要在原有模型中增加方法即可;對(duì)于后者,需要?jiǎng)?chuàng)建新的模型,然后考慮這個(gè)方法的定義,包括方法的名字、參數(shù)、返回值、異常和執(zhí)行過(guò)程。這個(gè)過(guò)程屬于MVC模式中M部分的設(shè)計(jì)。
(3)考慮輸入界面、功能和輸出界面之間如何關(guān)聯(lián)。需要編寫(xiě)控制器,也就是MVC模式中C部分的設(shè)計(jì)。控制器的設(shè)計(jì)需要考慮如下幾個(gè)方面的信息:
●需要從輸入界面獲取哪些信息,也就是視圖層向控制層傳遞哪些信息;
●需要調(diào)用JavaBean的哪個(gè)方法,需要傳遞什么信息,這些信息屬于從控制層向模型層傳遞的信息;
●是否需要把模型執(zhí)行的結(jié)果傳遞給顯示界面,包含模型層向控制層傳遞信息和從控制層向視圖層傳遞信息兩個(gè)方面;
●根據(jù)模型的執(zhí)行結(jié)果選擇界面對(duì)用戶進(jìn)行響應(yīng)。
6.4信
息
存
儲(chǔ)
Web應(yīng)用的運(yùn)行模式是無(wú)狀態(tài)的請(qǐng)求/應(yīng)答模式。用戶在客戶端發(fā)送對(duì)服務(wù)器上某個(gè)資源的請(qǐng)求,可能是在地址欄中輸入地址,也可能是點(diǎn)擊網(wǎng)頁(yè)中的超級(jí)鏈接或者提交按鈕。服務(wù)器接收到請(qǐng)求之后,調(diào)用并執(zhí)行相應(yīng)的文件,把執(zhí)行的結(jié)果返回給客戶端。在這個(gè)過(guò)程中服務(wù)器不會(huì)主動(dòng)保存任何信息,每次發(fā)送的請(qǐng)求信息只能在本次使用,下一次訪問(wèn)的時(shí)候前一次的請(qǐng)求信息就不能使用了。例如,第一次訪問(wèn)時(shí)輸入的用戶名第二次就不存在了。
一個(gè)Web應(yīng)用中可能會(huì)涉及很多方面的信息,如當(dāng)前運(yùn)行網(wǎng)站相關(guān)的信息,與每個(gè)客戶端相關(guān)的信息,與每次執(zhí)行相關(guān)的信息,與每個(gè)頁(yè)面相關(guān)的信息(每次執(zhí)行可能涉及多個(gè)頁(yè)面),頁(yè)面中顯示的信息以及用戶提交的信息等。
在Web應(yīng)用中,信息的保存可以采用兩種方式:
●永久保存,保存到數(shù)據(jù)庫(kù)或者文件中。
●臨時(shí)保存,可以使用應(yīng)用服務(wù)器提供的功能進(jìn)行保存。
永久保存可以使用數(shù)據(jù)庫(kù)也可以使用文件。因?yàn)閿?shù)據(jù)庫(kù)通常由管理系統(tǒng)進(jìn)行維護(hù),所以多數(shù)時(shí)候都使用數(shù)據(jù)庫(kù),使用文件的情況比較少。網(wǎng)站的動(dòng)態(tài)信息通常都存放在數(shù)據(jù)庫(kù)中。例如,學(xué)校的成績(jī)查詢系統(tǒng)中學(xué)生的基本信息及成績(jī)信息應(yīng)該保存在數(shù)據(jù)庫(kù)中。
臨時(shí)保存需要使用服務(wù)器提供的功能。需要臨時(shí)保存的信息如下:
●與服務(wù)器相關(guān)的信息,例如服務(wù)器的運(yùn)行環(huán)境、運(yùn)行時(shí)使用的參數(shù)等。
●與每個(gè)用戶相關(guān)的信息,即每個(gè)用戶在訪問(wèn)網(wǎng)站過(guò)程中使用的信息,例如登錄信息和權(quán)限信息等。
●與每次請(qǐng)求相關(guān)的信息,這些信息只有在當(dāng)前請(qǐng)求有效。
●每個(gè)頁(yè)面使用的信息,這些信息僅僅在當(dāng)前頁(yè)面使用。
與服務(wù)器相關(guān)的信息是服務(wù)器啟動(dòng)的時(shí)候由系統(tǒng)生成的,有的是根據(jù)配置文件生成的。服務(wù)器為每個(gè)應(yīng)用提供這樣一個(gè)對(duì)象來(lái)保存這些信息,這個(gè)對(duì)象是ServletContext的對(duì)象,通常稱為application。在JSP中application是內(nèi)部對(duì)象,可以直接使用。在Servlet中可以先獲取這個(gè)對(duì)象,然后再使用這個(gè)對(duì)象。這個(gè)對(duì)象是訪問(wèn)這個(gè)網(wǎng)站的所有用戶共享的。如果希望保存一些所有用戶都使用的信息,則可以使用這個(gè)對(duì)象保存。典型的例子有,在一個(gè)公共聊天室中的聊天信息是大家都可以看到的,如果這個(gè)聊天信息不使用數(shù)據(jù)庫(kù)保存,就需要使用aplication對(duì)象保存。
與每個(gè)用戶相關(guān)的信息需要保存在session對(duì)象中,這個(gè)對(duì)象是HttpSession的對(duì)象。服務(wù)器為每個(gè)用戶創(chuàng)建一個(gè)session對(duì)象,這個(gè)session對(duì)象是與每個(gè)用戶關(guān)聯(lián)在一起的,即別人不能訪問(wèn)你的session對(duì)象,你也不可以訪問(wèn)別人的session對(duì)象。session在JSP中也是內(nèi)部對(duì)象,可以直接使用。在Servlet中需要先得到這個(gè)對(duì)象。session對(duì)象雖然是與每個(gè)人相關(guān)的,但卻是在服務(wù)器上保存的。session中存儲(chǔ)的信息,在客戶端的整個(gè)訪問(wèn)過(guò)程中都可以使用。如果希望在客戶端的整個(gè)訪問(wèn)過(guò)程中共享信息的話,可以使用session。典型的例子有:保存用戶登錄和權(quán)限信息;保存購(gòu)物車信息。當(dāng)瀏覽器關(guān)閉的時(shí)候,或者長(zhǎng)時(shí)間沒(méi)有訪問(wèn)服務(wù)器時(shí),系統(tǒng)會(huì)刪除這個(gè)對(duì)象。
服務(wù)器會(huì)為每個(gè)用戶的每一次請(qǐng)求創(chuàng)建一個(gè)對(duì)象request,這個(gè)對(duì)象是ServletRequest的對(duì)象。這個(gè)對(duì)象只在當(dāng)前訪問(wèn)有效,下一次訪問(wèn)就會(huì)創(chuàng)建一個(gè)新的request。服務(wù)器在處理用戶的請(qǐng)求時(shí)可能會(huì)調(diào)用多個(gè)文件,這多個(gè)文件屬于同一次請(qǐng)求,它們可以共享request對(duì)象。所以如果想在同一次請(qǐng)求的多個(gè)文件之間傳遞信息,可以使用request對(duì)象,這個(gè)功能在后面介紹的MVC模式中經(jīng)常使用。另外,用戶在客戶端發(fā)送請(qǐng)求時(shí)的所有信息都被封裝在request對(duì)象中,典型的信息是用戶輸入的地址以及在表單元素中輸入的信息。實(shí)際上,保存在request中的信息也可以保存在session中,因?yàn)閟ession中的信息是用戶專用的,并且可以保存。但是在request中保存的信息只在本次訪問(wèn)有效,如果使用session保存這些信息,就會(huì)浪費(fèi)服務(wù)器的資源,因?yàn)閟ession對(duì)象存儲(chǔ)在服務(wù)器上并且時(shí)間比較長(zhǎng)。
在某個(gè)頁(yè)面中使用的信息通??梢员4嬖趐ageContext中,它是org.apache.jasper.
runtime.PageContextImpl的對(duì)象。該對(duì)象相當(dāng)于某次請(qǐng)求過(guò)程中某個(gè)頁(yè)面對(duì)應(yīng)的方法中的一個(gè)變量。這個(gè)對(duì)象一般不被使用。
另外還有一個(gè)比較特殊的對(duì)象,即在客戶端存儲(chǔ)的對(duì)象,這個(gè)對(duì)象是cookie。有時(shí)候也會(huì)使用cookie傳遞信息,因?yàn)樗梢园研畔⒈4嬖诳蛻舳恕5诳蛻舳舜鎯?chǔ)信息有可能侵犯隱私,所以客戶端有可能禁用cookie。如果客戶端禁用cookie,就不能使用這個(gè)對(duì)象存儲(chǔ)信息了。因?yàn)閏ookie信息在本地保存,所以即使瀏覽器關(guān)閉了,下次訪問(wèn)網(wǎng)站的時(shí)候還可以使用,即每次在訪問(wèn)這個(gè)網(wǎng)站的時(shí)候客戶端會(huì)把這個(gè)信息傳遞到服務(wù)器上。一個(gè)典型的例子是:當(dāng)用戶第一次訪問(wèn)某個(gè)網(wǎng)站的時(shí)候需要登錄,但是第二次訪問(wèn)的時(shí)候就可以直接進(jìn)入了,不需要重新登錄。要訪問(wèn)cookie中的信息,可以通過(guò)request對(duì)象訪問(wèn)。如果想把cookie保存到客戶端,則需要使用response對(duì)象,這個(gè)對(duì)象也是每次請(qǐng)求都會(huì)創(chuàng)建的,它在JSP中是內(nèi)部對(duì)象,在Servlet中是方法的參數(shù)。
cookie與其他對(duì)象的最大區(qū)別是:cookie不是內(nèi)部對(duì)象,不保存在服務(wù)器上,可以長(zhǎng)期保存。但cookie依賴客戶端瀏覽器的設(shè)置,如果瀏覽器禁用cookie,cookie就不能正常工作了。服務(wù)器關(guān)閉的時(shí)候,不會(huì)影響cookie。
綜上所述,每個(gè)網(wǎng)站會(huì)為整個(gè)應(yīng)用維護(hù)一個(gè)application對(duì)象,該對(duì)象可以保存所有用戶共享的信息。網(wǎng)站會(huì)為每個(gè)客戶端創(chuàng)建一個(gè)session對(duì)象,使用這個(gè)對(duì)象可以保存某個(gè)用戶在整個(gè)訪問(wèn)過(guò)程中的信息。每次請(qǐng)求的時(shí)候,服務(wù)器會(huì)創(chuàng)建一個(gè)與這個(gè)請(qǐng)求對(duì)應(yīng)的request對(duì)象,這個(gè)對(duì)象主要是與這次請(qǐng)求相關(guān)。另外,僅僅在某次請(qǐng)求中使用的信息可以保存
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 行政專員費(fèi)用管理方案(3篇)
- 豪宅運(yùn)營(yíng)管理方案(3篇)
- 家禽飼料配方師培訓(xùn)課件
- 一歲前寶寶護(hù)理知識(shí)培訓(xùn)課件
- 日記新世紀(jì)游玩日記350字9篇
- 企業(yè)知識(shí)產(chǎn)權(quán)保護(hù)流程手冊(cè)含風(fēng)險(xiǎn)評(píng)估與應(yīng)對(duì)策略
- 想象作文假如我有一支神筆200字(13篇)
- 家庭農(nóng)場(chǎng)經(jīng)營(yíng)管理與農(nóng)業(yè)技術(shù)推廣合同
- 可愛(ài)的小倉(cāng)鼠200字(9篇)
- 商務(wù)合同起草與審核指導(dǎo)手冊(cè)
- 男女導(dǎo)尿并發(fā)癥
- 車間現(xiàn)場(chǎng)品質(zhì)培訓(xùn)
- 央視中秋詩(shī)會(huì)活動(dòng)方案
- 腦轉(zhuǎn)移瘤護(hù)理查房
- 2025至2030年中國(guó)未來(lái)產(chǎn)業(yè)市場(chǎng)運(yùn)營(yíng)態(tài)勢(shì)及發(fā)展趨向研判報(bào)告
- 滬阿姨奶茶管理制度
- 2025至2030中國(guó)乙醇行業(yè)市場(chǎng)深度調(diào)研及發(fā)展趨勢(shì)與投資方向報(bào)告
- 溫州科目一試題及答案
- 2025年中國(guó)釩催化劑行業(yè)市場(chǎng)前景預(yù)測(cè)及投資價(jià)值評(píng)估分析報(bào)告
- (高清版)DGJ 08-100-2003 低壓用戶電氣裝置規(guī)程
- 2025高中數(shù)學(xué)教師課標(biāo)考試模擬試卷及答案(五套)
評(píng)論
0/150
提交評(píng)論