服務器端開發(fā)技術Servlet_第1頁
服務器端開發(fā)技術Servlet_第2頁
服務器端開發(fā)技術Servlet_第3頁
服務器端開發(fā)技術Servlet_第4頁
服務器端開發(fā)技術Servlet_第5頁
已閱讀5頁,還剩123頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

服務器端開發(fā)技術Servlet

服務器端開發(fā)技術-Servlet第一節(jié).Servlet概述第二節(jié).Servlet的開發(fā)環(huán)境及程序結構第三節(jié).Servlet基礎第四節(jié).會話跟蹤第五節(jié).JDBC訪問數據庫第一節(jié)Servlet概述

1.Servlet的作用

Servlet技術是使用Java技術開發(fā)Web應用的基礎,后面講述的JSP也是在它的基礎上發(fā)展起來的。Servlet技術支持創(chuàng)建動態(tài)的Web頁面,即頁面內容根據用戶輸入或其他變量數據而改變的Web頁面(動態(tài)頁面),這就極大地增強了應用開發(fā)的能力。

Servlet是一個基于Java語言實現的服務器端組件,它可以被用來擴充Web服務器的功能。Servlet可以簡單地看作一個Java類。最終該Java類運行在一個服務器端的Servlet容器內,通過容器提供會話管理和對象生命周期管理。

2.Servlet的優(yōu)點

Servlet效率更高、更容易編程、功能更強、更安全和具有良好的可移植性,因而成為主流的動態(tài)網站技術。

Servlet最大的優(yōu)勢在于它的高性能,Servlet采用了和CGI不同的運行方式。其次,在默認情況下,Servlet以單實例多線程的方式工作。

Servlet繼承了Java的所有優(yōu)勢,包括易升級以及平臺無關性,在進行程序編寫的時候可以調用Java所提供的大量的API。

3.Servlet的基本工作原理

一個Servlet在服務器端由稱為Servelt容器(也有稱為servlet引擎)的程序來解釋執(zhí)行,可以把Servlet理解成Server上的applet,Servlet在被調用后會被動態(tài)地載入到容器由容器解釋執(zhí)行,這樣通過Servlet包含的功能就擴展了Web服務器的功能。

Web服務器和Servlet容器可以是兩個獨立的松耦合的應用程序(圖表5-2),也可以是緊密集成的一個應用程序(圖表5-3)。從圖表5-2和圖表5-3顯示了一個典型的基于Servlet和JSP(一種Servlet的變體)的Web應用程序,包括若干Servlet或者JSP文件,也可能包含許多HTML文件和圖片等其他資源文件。客戶端對于Servet的訪問先到達WebServer,如果訪問的是HTML文件和圖片這樣的靜態(tài)資源文件,WebServer會直接處理并給出響應,而如果訪問的是Servlet,那么通過Servlet容器去執(zhí)行Servet并給出響應。瀏覽器或者其他應用程序一般通過HTTP協(xié)議訪問WebServer。第五章. 服務器端開發(fā)技術-Servlet第一節(jié).Servlet概述第二節(jié).Servlet的開發(fā)環(huán)境及程序結構第三節(jié).Servlet基礎第四節(jié).會話跟蹤第五節(jié).JDBC訪問數據庫第二節(jié)Servlet的開發(fā)環(huán)境及程序結構1.開發(fā)環(huán)境安裝及測試

(1)開發(fā)環(huán)境概述進行Servlet開發(fā)所需要的基本環(huán)境是JSDK(JavaServletDevelopmentKit)、一個支持Servlet的Web服務器、集成開發(fā)工具。

在本書中采用了JBuilder進行編輯、編譯和調試Servlet。JSDK包含了編譯Servlet應用程序所需要的Java類庫以及相關的文檔。常用的支持Servet的容器有Resin、ApacheTomcat、IBMWebsphere、BEAWebLogicServer等等。本教材面向的是學校的教學,在選擇開發(fā)軟件環(huán)境的時候必須考慮學校和學生的實際條件。因為Resin對資源要求不高,配置比較容易,學校實驗室和學生本人都有條件使用Resin。 因此,在本書關于Servle和JSP的開發(fā)中,都將采用Resin作為Web服務器。其下載Resin的網址如下:/download/index.xtp(2)Resin的安裝安裝Resin的步驟如下:安裝JDK在安裝Resin之前要先安裝JDK(建議版本在1.4以上)??截怰esin目錄安裝完JDK之后如果要安裝Resin,只需要把Resin文件夾(下載后的Resin壓縮文件展開后的文件夾)拷貝到機器的特定目錄下就可以了,不需要其他配置操作。啟動RESIN拷貝完畢后,要啟動RESIN直接執(zhí)行httpd.exe即可。測試啟動后,即可測試是否工作正常,方法是在瀏覽器里面輸入http://機器名:8080即可(如果是本機也可以輸入http://localhost:8080)。Resin安裝完畢后的目錄結構大致如下圖:

從上圖可以看出,Resin安裝在d:\resin-2.1.16文件夾下,版本號是2.1.16。 其中在子文件夾bin下的httpd.exe是可執(zhí)行程序,子文件夾conf目錄下存放配置文件。建議把所開發(fā)的應用程序存放在路徑為Webapps文件夾下。 另外注意,在lib子文件夾下有很多jar文件,其中jsdk23.jar是執(zhí)行servlet時需要到的包,這個文件里面包含與開發(fā)Servlet有關的包和很多類,我們在Jbulider或者其他開發(fā)工具中要指定使用這個包。(3)Resin環(huán)境測試 安裝好Resin后,我們可以啟動Resin服務器,方式是執(zhí)行httpd.exe即可,啟動后屏幕顯示結果如下圖,仔細確認屏幕,如果其上沒有出錯提示,那么表示Resin已經啟動。啟動后屏幕顯示結果如下:

為驗證Resin是否工作正常,我們需要打開瀏覽器測試一下,在地址欄輸入http://localhost:8080,如果屏幕出現類似下面內容,表示Resin工作正常。

2.配置Web應用 一般一個Web應用發(fā)布時都會有一個自己發(fā)布區(qū),這個發(fā)布區(qū)往往對應一個物理的目錄,所有發(fā)布的html文件、圖片文件、樣式表、Servlet類、JSP文件和其他一些描述性文件等都要放到這個目錄及其子目錄下。(1)Resin的配置文件

Resin的配置文件是resin.conf,位于安裝目錄的conf目錄下(比如D:\resin-2.1.16\conf)。resin.conf是一個XML格式的配置文件,這個配置文件由很多標記組成。 <resource-ref>……</resource-ref>標記對

<http-server>……</http-server>標記對

<resource-ref>……</resource-ref>標記對

<resource-ref>……</resource-ref>標記是用來配置Resin所使用的資源,一般用來聲明管理資源,如數據庫驅動程序等。<http-server></http-server>標記對 在<http-server></http-server>標記對中的配置和resin的JavaWeb服務器有關。找到<web-app>,在<app-dir></app-dir>標記對里的id屬性和app-dir子標記非常重要。id屬性表示該應用的Web路徑。如<web-appid=′/shopping′>,表示該應用在Web上訪問的時候應該用http://機器名/shopping/來訪問。app-dir屬性表示該應用的實際路徑。如:<app-dir>d:\resin\doc\test</app-dir>表示該應用在d:\resin\doc\test目錄下。(2)配置自己的Web應用 假設我們有一個welcome.html的網頁、一個counter.jsp的JSP文件和一個類名為RequestInfoExample.class的Servlet,現在要發(fā)布它們到一個支持Java的Web服務器上,訪問的URL分別為:

http://localhost:8080/myweb/welcome.htmlhttp://localhost:8080/myweb/counter.jsp修改Resin的配置文件 為了做到這點,需要修改Resin的配置文件resin.conf,在該配置文件中的<http-server></http-server>中需要增加一個和其他<web-app></web-app>并列的標記,指定id=‘/myweb’,同時在<web-app>的子標記中指定<app-dir>D:\resin-2.1.16\myweb</app-dir>,其他標記和值暫時忽略不變。該配置文件內容如下:

<web-appid='/myweb'><app-dir>D:\resin-2.1.16\myweb</app-dir>……</web-app>

修改配置文件后,一定記住要重新啟動Resin,以便使新的修改被重新加載從而生效。HTML網頁的發(fā)布及測試 使用記事本或者網頁編輯工具編輯如下html代碼并保存到前面配置的D:\resin-2.1.16\myweb目錄下,文件名為welcome.html。welcome.html內容如下:<html><body>Welcome,haveaniceday.</body></html>

打開瀏覽器,在地址欄輸入http://localhost:8080/myweb/welcome.html,就可以看到網頁的執(zhí)行結果。

JSP的發(fā)布及測試 同樣,使用記事本或者網頁編輯工具編輯如下JSP代碼并保存到前面配置的D:\resin-2.1.16\myweb目錄下,文件名為counter.jsp。counter.jsp,其內容如下:<%@pagecontentType="text/html;charset=GBK"language="java"%><%Integercount=null;synchronized(application){count=(Integer)application.getAttribute("basic.counter");if(count==null) count=newInteger(0);count=newInteger(Value()+1);application.setAttribute("basic.counter",count);}%><html><head><title>Counter</title></head><bodybgcolor=#ffffff><h1>歡迎,訪問次數:<%=count%></h1></body></html>

打開瀏覽器,在地址欄輸入http://localhost:8080/myweb/counter.jsp,就可以看到JSP的執(zhí)行結果。多刷新幾次或者關閉瀏覽器重新訪問看看結果會如何。3.第一個Servlet

(1)編寫及編譯ServletJavaServletAPI是一個標準的Java擴展程序包,和Servlet相關的有javax.servlet和javax.servlet.http兩個Java包。對于想開發(fā)基于客戶自定義協(xié)議的開發(fā)者,應該使用javax.servlet包中的類與接口;對于僅利用HTTP協(xié)議與客戶端進行交互的開發(fā)者,則只需要使用javax.servlet.http包中的類與接口進行開發(fā)即可。

Servlet的結構下面一個例子RequestInfoExample.java打印前端請求參數,代碼如下:importjavax.servlet.*;importjavax.servlet.http.*;importjava.io.*;importjava.util.*;publicclassRequestInfoExampleextendsHttpServlet{publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsIOException,ServletException{response.setContentType("text/html");PrintWriterout=response.getWriter();out.println("<html>");out.println("<body>");out.println("<head>");out.println("<title>RequestInformationExample</title>");out.println("</head>");out.println("<body>");out.println("<h3>RequestInformationExample</h3>");out.println("Method:"+request.getMethod());out.println("<br>RequestURI:"+request.getRequestURI());out.println("<br>Protocol:"+request.getProtocol());out.println("<br>PathInfo:"+request.getPathInfo());out.println("<br>RemoteAddress:"+request.getRemoteAddr());out.println("</body>");out.println("</html>");}publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException,ServletException{doGet(request,response);}}

有關該servlet程序結構說明∶一般基于HTTP協(xié)議的servlet要引入javax.servlet和javax.servlet.http包RequestInfoExample從類HttpServlet派生,HttpServlet為基于HTTP協(xié)議的Servlet提供了基本的支持;

HttpServletRequest對象包含了客戶端請求的信息,可以通過該參數取得客戶端的一些信息(例如IP地址、瀏覽器類型等)以及HTTP請求類型(例如GET、HEAD、POST、PUT等);HttpServletResponse對象用于完成Servlet與客戶端的交互,通過調用HttpServletResponse.getWriter方法取得向客戶端進行輸出的輸出流(PrintWriter的對象),向客戶端發(fā)送HTML頁面。編寫了doGet方法,對于HTMLPOST請求,調用Servlet的doPost()方法。

編譯Servlet(RequestInfoExample.java) 利用Jbuilder對Servlet代碼進行編譯,在編譯的時候一定記住要在Jbuilder中設置JSDK的路徑,否則會找不到Servlet編譯需要的類。編譯后會生成RequestInfoExample.class類文件,該文件要發(fā)布到Resin服務器的myweb應用中,以便客戶端調用。

(2)配置Resin以調用Servlet Servlet編譯后要發(fā)布到Resin服務器的指定目錄下,然后通過URL去調用,就象調用HTML文件和JSP文件一樣。Servlet的發(fā)布稍微麻煩一些,主要有兩個工作:把類編譯后的類文件拷貝到特定目錄 如果要作為myweb應用的一部分發(fā)布,那么需要拷貝RequestInfoExample.class到D:\resin-2.1.16\myweb\WEB-INF\classes目錄下。如果沒有該目錄,手工創(chuàng)建即可。指定要發(fā)布的Servlet

需要在Resin配置文件resin.conf里指定要發(fā)布的Servlet,包括要讓客戶端調用的Servlet,調用的映射地址,并且重新啟動Resin。一般Resin的配置文件發(fā)生改動,或者發(fā)布的Servlet類有變化時都需要重新啟動Resin。

為了調用RequestInfoExampleServlet,resin配置文件還針對myweb應用增加下面黑體字的內容:<web-appid='/myweb'><app-dir>D:\resin-2.1.16\myweb</app-dir>

<servletservlet-name='RequestInfoName' servlet-class='RequestInfoExample'/> <servlet-mappingurl-pattern='/RequestInfo'servlet-name='RequestInfoName'/></web-app>這段代碼中的servlet這一段聲明了你要調用的Servlet的Java類是RequestInfoExample(servlet-class=‘RequestInfoExample’,不帶.class擴展名);同時指定它的邏輯名字是RequestInfoName(servlet-name=RequestInfoName),邏輯名字和類名不同(當然也可以相同);servlet-mapping聲明邏輯名字為RequestInfoName的Servet訪問時候可以通過地址/RequestInfo訪問,地址/RequestInfo和Servelt的類名可以相同也可以不同。在上述配置下,可以使用如下URL去訪問該Servlet:

http://localhost:8080/myweb/RequestInfo

(訪問方式1)

可以看出配置文件中的url-pattern='/RequestInfo'和<web-appid='/myweb'>共同決定了Servlet的調用URL(/myweb/RequestInfo)。 使用配置可以讓URL中訪問Servlet時候的路徑和Servlet類的名字無關,這樣即使Servlet的類的名字修改了,對外訪問的URL也可以不變,這樣帶來了很大的靈活性。當然,訪問的時候,也可以直接通過類名或者邏輯名字訪問Servlet,訪問URL如下:(訪問方式2)

http://localhost:8080/myweb/servlet/RequestInfoExample

(訪問方式3)

http://localhost:8080/myweb/servlet/RequestInfoName第五章. 服務器端開發(fā)技術-Servlet第一節(jié).Servlet概述第二節(jié).Servlet的開發(fā)環(huán)境及程序結構第三節(jié).Servlet基礎第四節(jié).會話跟蹤第五節(jié).JDBC訪問數據庫第三節(jié)Servlet基礎5.3.1Servlet的生命周期 一個Javaservlet具有一個生命周期,這個生命周期定義了一個Servlet如何被載入并被初始化,如何接收請求并作出對請求的響應,如何被從服務中清除。Servlet的生命周期被javax.servlet.Servlet這個接口所定義。

所有的JavaServlet都會直接地或間接地執(zhí)行javax.servlet.Servlet接口,這樣它才能在一個Servlet引擎中運行。Servlet引擎是Web服務器按照ServletAPI定制的擴展。Servlet引擎提供網絡服務,能夠理解MIME請求,并提供一個運行Servlet的容器。

理解并掌握Servlet的生命周期極為重要,只有理解了Servlet的生命周期里涉及的方法、方法的作用和方法的調用時機,才能掌握Servlet編程。javax.servlet.Servlet接口定義了在Servlet的生命周期中特定時間以及特定順序被調用的方法(下圖)。1、Servlet的解析、載入和初始化

Web容器(含Servlet引擎)在啟動時或者在一個Servlet被請求時載入一個Servlet并對Servlet進行初始化,在這一過程中,Servlet可以讀取一些固定存儲的數據、初始化JDBC的連接以及建立與其他資源的連接。

2、Servlet處理請求

Servlet被初始化之后,它可以處理來自客戶端的請求,每一個來自客戶端的請求都被描述成一個ServletRequest對象,而Servlet的響應被描述成一個ServletResponse對象。當客戶端發(fā)出請求時,Servlet引擎?zhèn)鬟f給Servlet一個ServletRequest對象和一個ServletResponse對象,這兩個對象作為參數傳遞到service()方法中。

3、Servlet的卸載 當Servlet引擎決定卸載一個Servlet時(如引擎被關閉等),這個引擎必須允許Servlet釋放正在使用的資源并存儲有關資料。引擎會調用Servlet的destroy()方法。

Servlet引擎可以自由的在任何時候使用或清除一個Servlet。卸載一個Servlet之前,Servlet引擎會等待所有的service()方法完成或超時結束。 一個Servlet被卸載時,引擎將不會給Servlet發(fā)送任何請求。引擎必須釋放Servlet并完成無用存儲單元的收集。5.3.2Servlet相關接口和類

Servlet相關的接口和類共有3個:Servlet接口,GenericServlet類和HttpServlet類。Servlet接口定義了所有的Servlet的基本功能,作為一個接口,其他的Servlet(GenericServlet和HttpServlet)必須實現其中的方法。GenericServlet抽象類實現了Servlet接口,定義了一個通用的,與協(xié)議無關的Servlet。HttpServlet定義了一個抽象類,它繼承了GenericServlet抽象類,支持基于HTTP協(xié)議的Servlet,一般自寫的Servlet都是為了處理HTTP請求的,所以應當繼承HttpServlet類。1、Servlet接口

Servlet接口定義了所有的Servlet的基本功能,以及生命周期等方法。其方法見下面的內容:

publicvoidinit(ServletConfigconfig)throwsServletException;

Servlet引擎會在Servlet實例化之后,置入服務之前精確地調用init方法。在調用service方法之前,init方法必須成功退出。

publicvoidservice(ServletRequestrequest,ServletResponseresponse)throwsServletException,IOException;

Servlet引擎調用這個方法以允許Servlet響應請求。這個方法在Servlet未成功初始化之前無法調用。在Servlet被初始化之前,Servlet引擎能夠封鎖未決的請求。在一個Servlet對象被卸載后,直到一個新的Servelt被初始化,Servlet引擎不能調用這個方法。publicvoiddestroy();當一個Servlet被從服務中去除時,Servlet引擎調用這個方法。在這個對象的service方法所有線程未全部退出或者沒被引擎認為發(fā)生超時操作時,destroy方法不能被用。publicServletConfiggetServletConfig();返回一個ServletConfig對象,作為一個Servlet的開發(fā)者,你應該通過init方法存儲ServletConfig對象以便這個方法能返回這個對象。GenericServlet在執(zhí)行這個接口時,已經這樣做了。publicStringgetServletInfo();允許Servlet向主機的Servlet運行者提供有關它本身的信息。返回的字符串應該是純文本格式而不應有任何標志(例如HTML,XML等)。

2、GenericServlet類

GenericServlet類是最基本的類之一。程序員要編寫Servlet應用程序,一般要繼承GenericServlet類或它的子類HttpServlet類。它提供了一個簡單的方案來執(zhí)行有關Servlet生命周期的方法以及在初始化時對ServletConfig對象和ServletContext對象進行說明。該類包含的方法如下:

init等生命周期方法的作用和前面介紹的Servlet接口類似,注意以下兩個方法在和Servlet容器交互時會使用。publicServletConfiggetServletConfig()返回一個通過這個類的init方法產生ServletConfig對象的說明。publicServletContextgetServletContext()它將會調用ServletConfig對象的同名的方法。

3、HttpServlet類

HttpServlet是從GenericServlet繼承而來,因此它具有GenericServlet類似的方法和對象,HttpServlet是使用Servlet編程直接用到的類,它支持HTTP的post和get等方法。具體方法如下:

init()方法的使用

在Servlet的生命期中,僅執(zhí)行一次init()方法。它是在服務器裝入Servlet時執(zhí)行的??梢耘渲梅掌鳎栽趩臃掌骰蚩蛻魴C首次訪問Servlet時裝入Servlet。無論有多少客戶機訪問Servlet,都不會重復執(zhí)行init()。service()方法使用

service()方法是Servlet的核心。每當一個客戶請求一個HttpServlet對象,該對象的service()方法就要被調用,而且傳遞給這個方法一個“請求”(ServletRequest)對象和一個“響應”(ServletResponse)對象作為參數。在HttpServlet中已經實現了service()方法,該方法會根據請求調用與HTTP請求的方法相應的doXXX功能。destroy()方法destroy()方法僅執(zhí)行一次,即在服務器停止且卸裝Servlet時執(zhí)行該方法。典型的,將Servlet作為服務器進程的一部分來關閉。缺省的destroy()方法通常是符合要求的,但也可以覆蓋它,典型的是管理服務器端資源。例如,如果Servlet在運行時會累計統(tǒng)計數據,則可以編寫一個destroy()方法,該方法用于在未裝入Servlet時將統(tǒng)計數字保存在文件中。另一個示例是關閉數據庫連接。GetServletConfig()方法GetServletConfig()方法返回一個ServletConfig對象,該對象用來返回初始化參數和ServletContext。ServletContext接口提供有關servlet的環(huán)境信息。GetServletInfo()方法GetServletInfo()方法是一個可選的方法,它提供有關servlet的信息,如作者、版本、版權。

4、使用HttpServlet類進行Servlet開發(fā)

創(chuàng)建一個HTTPServlet,通常涉及下列四個步驟:擴展HttpServlet抽象類。重載適當的方法。如覆蓋(或稱為重寫)service()方法或者doGet()和doPost()方法。獲取信息如果有HTTP請求信息的話,獲取該信息。用請求對象(HttpServletRequest的對象,見后面HttpServletRequest的說明)來檢索HTML表單所提交的數據或URL上的查詢字符串?!罢埱蟆睂ο蠛刑囟ǖ姆椒ㄒ詸z索客戶機提供的信息。生成HTTP響應。用響應對象(HttpServletResponse的對象,見后面的HttpServletResponse的說明)生成響應,并將它返回到發(fā)出請求的客戶機上。一個servlet樣例(ServletSample.java)如下:

importjava.io.*;importjava.util.*;importjavax.servlet.*;importjavax.servlet.http.*;//第一步:擴展HttpServlet抽象類。

publicclassServletSampleextendsHttpServlet{//第二步:重寫service方法publicvoidservice(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{System.out.println("in");//調試用,判斷是否進入該函數

StringmyName="";//第三步:獲取HTTP請求信息

myName=request.getParameter("myName");if((myName=="")||(myName==null))myName="guest";//第四步:生成HTTP響應。

PrintWriterout=response.getWriter();response.setContentType("text/html;charset=GBK");

out.println("<head><title>測試例子</title></head>");out.println("<body>");out.println("<h1>這是一個Servlet測試例子</h1>");out.println("<p>"+myName+"你好,這是一個僅給出HTML響應的Servlet例子.");out.println("<p>"+"請輸入http://localhost:8080/myweb/servlet/ServletSample?myName=John");out.println("</body></html>");System.out.println("htmlok");//調試用,判斷是否前面語句正常結束

out.flush();}}

上述ServletSample類繼承了HttpServlet抽象類,同時它覆蓋了父類的service()方法。在重寫的service()方法中,獲取HTTP請求中的一個任選的參數(myName)。然后設置設定響應的內容的類型,并從響應對象(response)獲取PrintWriter對象(out),然后使用PrintWriter的print()和println()方法給請求的客戶端程序響應一個HTML格式的內容。 將Servlet的類ServletSample發(fā)按照前面介紹的技術來發(fā)布到myweb應用中,需要調用Servlet或Web應用程序,可以使用下列任一種方法:由URL調用、在<FORM>標記中調用。URL調用Servlet()在發(fā)布Servlet的Resin服務器上打開瀏覽器,輸入如下URLhttp://localhost:8080/myweb/servlet/ServletSample?myName=John如果在其他機器上,上述URL的localhost可以換成發(fā)布Servlet的Resin服務器的主機名。在<FORM>標記中指定Servlet可以在<FORM>標記中調用Servlet。HTML格式使用戶能在Web頁面(即從瀏覽器)上輸入數據,并向Servlet提交數據。例如:<html><body><FORMMETHOD="get"ACTION="http://localhost:8080/myweb/servlet/ServletSample"><OL><INPUTTYPE="radio"NAME="myName"VALUE="Zhang">ZhangJun<BR><INPUTTYPE="radio"NAME="myName"VALUE="Admin">Administrator<BR></OL>

<inputtype="submit"value="確定"></FORM></body></html>5.3.3請求/響應類及接口

當一個servlet接收來自客戶端的調用請求(通過service,doXXX方法),

它接收兩個對象:

一個是ServletRequest和ServletResponse。ServletRequest類概括從客戶端到服務器之間的聯系。ServletResponse類概括從servlet返回客戶端的聯系,用于Servlet向客戶發(fā)送響應。HttpServletRequest接口繼承了ServletRequest接口,他可以讓

servlet獲取更多的HTTP協(xié)議特性數據。HttpServletResponse接口繼承了ServletResponse接口,它為Servlet返回HTTP回應給客戶端提供了支持。

四個接口里定義的方法

1、ServletRequestpublicStringgetParameter(Stringname)

以String對象返回指定的參數的值,如果這個參數不存在返回空值。publicString[]getParameterValues(Stringname);

通過String對象的數組返回指定參數的值,如果這個參數不存在,該方法返回一個空值。publicEnumerationgetParameterNames()

返回所有參數名的String對象列表,如果沒有輸入參數,該方法返回一個空值。publicvoidsetAttribute(Stringname,Objectobject)

在請求中添加一個屬性,這個屬性可以被其他可以訪問這個請求對象的對象使用。publicObjectgetAttribute(Stringname)

返回請求中指定屬性的值,如果這個屬性不存在,就返回一個空值。publicEnumerationgetAttributeNames()

返回包含在這個請求中的所有屬性名的列表。2、HttpServletRequest

該接口繼承了ServletRequest接口,在ServletRequest接口的方法基礎上,需要進一步掌握以下2個方法:publicCookie[]getCookies()

返回一個數組,該數組包含這個請求中當前的所有Cookie。如果這個請求中沒有Cookie,返回一個空數組。publicHttpSessiongetSession()publicHttpSessiongetSession(booleancreate)

返回與這個請求關聯的當前的有效的session。如果調用這個方法時沒帶參數,那么在沒有session與這個請求關聯的情況下,將會新建一個session。

getCookies和getSession方法分別用于支持Cookie和Session,在后面將詳細介紹它們的使用。

3、ServletResponsepublicPrintWritergetWriterthrowsIOException

這個方法返回一個PringWriter對象用來記錄格式化的響應實體。publicvoidsetContentType(Stringtype)

這個方法用來設定響應的content類型。publicStringgetCharacterEncoding()

返回MIME實體的字符編碼。在HTTP協(xié)議中,這個信息被通過Accept-Charset傳送到Servlet引擎。publicServletOutputStreamgetOutputStream()throwsIOException

返回一個記錄二進制的響應數據的輸出流。publicvoidsetContentLength(intlength)

設置響應的內容的長度,這個方法會覆蓋以前對內容長度的設定。為了保證成功地設定響應頭的內容長度,在響應被提交到輸出流之前必須調用這個方法。4、HttpServletResponseHttpServletResponse描述一個返回到客戶端的HTTP回應。通過該接口可以利用HTTP協(xié)議規(guī)定的頭信息。publicvoidaddCookie(Cookiecookie)

在響應中增加一個指定的Cookie??啥啻握{用該方法以定義多個Cookie。為了設置適當的頭域,該方法應該在響應被提交之前調用。publicvoidsendRedirect(Stringlocation)throwsIOException;

使用給定的路徑,給客戶端發(fā)出一個臨時轉向的響應。給定的路徑必須是絕對URL。

5、Servlet綜合示例

要求達到的功能:用戶在界面上輸入的姓名(文本框)和選擇要購買的商品(多選按鈕)后點擊提交按鈕,提交給后臺Servlet處理Servlet對用戶的點擊的商品的價格給出響應,響應的內容為顯示該用戶的名字,同時顯示用戶購買的商品以及商品總價假設頁面上顯示的商品包括MP3,DV,Radio,Pen,這4種商品的價錢在Servlet里面用變量維護。

HTML頁面:

要完成這樣的功能,考慮使用一個HTML頁面(commodity.html)完成商品選擇和提交。HTML文件里面包含一個Form,Form里面包含一個文本框,同時包括多選按鈕來顯示已有4種商品供用戶選擇。頁面外觀參考如下:

Servlet:

另外,一個Servlet(CommodityServlet)接收Form提交的請求并進行處理,在該Servlet中獲取用戶輸入的姓名,同時獲取選擇的商品,通過商品名查找該商品的價格,然后給用戶響應,響應內容及格式參考下圖。

commodity.html:<HTML><body><br><center><formaction="/myweb/servlet/CommodityServlet"method="post"><tablewidth="50%"align="center"><tr><tdwidth="35%">名字</td><td><inputtype="text"name="name"size="20"></td></tr><tr><tdcolspan="2">商品如下:</td></tr><tr><td><inputname="goods"type="checkbox"value="MP3">MP3</td><td><inputname="goods"type="checkbox"value="DV">DV</td></tr><tr><td><inputname="goods"type="checkbox"value="Radio">收音機</td><td><inputname="goods"type="checkbox"value="Pen">鋼筆</td></tr></table><inputtype="submit"name="submit"value="提交"></form></center></body></HTML>注意commodity.html提交的兩個參數為name和goods,其中goods可能會同時提交多個值。CommodityServlet.java:importjava.io.*;importjava.util.*;importjavax.servlet.*;importjavax.servlet.http.*;//第一步:擴展HttpServlet抽象類。

publicclassCommodityServletextendsHttpServlet{//第二步:重寫service方法

publicvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{StringuserName="";StringinputCommodity[]=null;//用戶提交的商品數組

doubletotalPrice=0;String[]commidty=null;//現有的商品數組

double[]price=null;//現有的商品對應的價格

commidty=newString[4];price=newdouble[4];commidty[0]="MP3";price[0]=245;commidty[1]="DV";price[1]=1225;commidty[2]="Radio";price[2]=48;commidty[3]="Pen";price[3]=120;PrintWriterout=response.getWriter();//第三步:獲取HTTP請求信息

userName=request.getParameter("name");inputCommodity=request.getParameterValues("goods");if((userName=="")||(userName==null)) userName="guest";//第四步:生成HTTP響應。

response.setContentType("text/html;charset=GBK");out.println("<head><title>商品匯總</title></head>");out.println("<body>");out.println("姓名:"+userName);if(inputCommodity==null)//如果沒有選擇商品就提示并結束方法執(zhí)行

{ out.println("<br>請回去選擇商品."); return;}out.println("<br>購買的商品如下:");for(inti=0;i<inputCommodity.length;i++){ out.print("<br>"+inputCommodity[i]); for(intj=0;j<commidty.length;j++) {if(inputCommodity[i].equals(inputCommodity[j])) {totalPrice+=price[j]; out.println("\t\t單價"+price[j]); break; } }}out.println("<br><hr>總價為"+totalPrice);out.println("</body></html>");out.flush();}}6、漢字亂碼處理經常在訪問一些JSP或者Servlet的程序時,在瀏覽器一端會發(fā)現如下問題:漢字都成了’?’;瀏覽器中看到的Servlet頁面中的漢字都成了亂碼;

JAVA應用程序界面中的漢字都成了方塊;

Jsp/Servlet頁面無法顯示GBK漢字;

Jsp/Servlet不能接收form提交的漢字;

JSP/Servlet數據庫讀寫無法獲得正確的內容。

要明白這些問題的原因,需要了解一些編碼知識。英文字符一般是以一個字節(jié)來表示的,最常用的編碼方法是ASCII。但一個字節(jié)最多只能表示128個字符(最高位沒有使用),而漢字成千上萬,所以現在都以雙字節(jié)來表示漢字,為了能夠與英文字符分開,每個字節(jié)的最高位一定為1,這樣雙字節(jié)最多可以表示64K個字符。我們經常碰到的編碼方式有GB2312、GBK、BIG5、UNICODE等。

Java編程語言默認的編碼方式是UNICODE,而我們通常使用的數據庫及文件都是基于GB2312編碼的。為此,在Java編程過程中,向網頁輸出中文字符串的時候(如用out.println(string),string是含中文的字符串),必須作UNICODE到GBK的轉換。通過合理設置請求和響應的字符集可以解決亂碼問題。下面通過一個例子來掌握中文的處理。importjava.io.*;importjavax.servlet.*;importjavax.servlet.http.*;publicclassChineseProcessextendsHttpServlet{ publicvoidservice(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ StringmyName=null; PrintWriterout=response.getWriter();

//從HTTP請求的頭信息中獲取客戶端的語言設置

StringclientLanguage=request.getHeader("Accept-Language"); System.out.println("clientLanguage="+clientLanguage);

//簡體中文瀏覽器

if(clientLanguage.equals("zh-cn")) { request.setCharacterEncoding("GBK"); response.setContentType("text/html;charset=GBK"); }

//繁體中文瀏覽器

elseif(clientLanguage.equals("zh-tw")) { request.setCharacterEncoding("BIG5"); response.setContentType("text/html;charset=BIG5"); }elseif(clientLanguage.equals("jp")) { request.setCharacterEncoding("SJIS"); response.setContentType("text/html;charset=SJIS"); } //缺省認為是英文瀏覽器

else{ request.setCharacterEncoding("ISO-8859-1"); response.setContentType("text/html;charset=ISO-8859-1"); } myName=request.getParameter("name"); if((myName.equals(""))||(myName==null)) myName="成吉思汗"; System.out.println("\nmyName="+myName); out.println("<head><title>中文例子</title></head>"); out.println("<body>"); out.println("<h1>簡單的中文(例子)</h1>"); out.println("<p>收到請求name為"+myName); }}

在Servlet里讀取請求和給出響應的時候,一般要先從HTTP請求的頭信息中獲取客戶端的語言設置(request.getHeader(“Accept-Language”),然后根據客戶端不同語言設置去設置請求對象request的字符編碼(request.setCharacterEncoding(“GBK”))以及響應對象response的的內容類型中的字符集(response.setContentType(“text/html;charset=GBK”))。然后在瀏覽器輸入URL為http://localhost:8080/myweb/servlet/ChineseProcess?name=張三,可以看到瀏覽器返回結果沒有亂碼。

第五章. 服務器端開發(fā)技術-Servlet第一節(jié).Servlet概述第二節(jié).Servlet的開發(fā)環(huán)境及程序結構第三節(jié).Servlet基礎第四節(jié).會話跟蹤第五節(jié).JDBC訪問數據庫第四節(jié)會話跟蹤5.4.1會話跟蹤概述

HTTP是一個沒有狀態(tài)的協(xié)議。在客戶端(瀏覽器)和服務器的一次典型的交互過程中,先由客戶發(fā)出請求(請求中攜帶一些數據),請求及其數據通過網絡傳輸到服務器,服務器讀出數據并處理,進而會給出客戶端處理的響應,響應中攜帶服務器返回給客戶端的數據(對于瀏覽器客戶端,一般將響應數據包含到頁面中,返回給瀏覽器一個HTML格式的數據)。 一般將客戶端和服務器的多次密切相關的交互稱作一次會話,一次會話中包含一次或者多次請求和響應,這多次請求和響應之間可以共享數據,它們共同完成了特定的業(yè)務功能。

常用的跟蹤技術:URL改寫、隱藏表單域、Cookie和Session技術。5.4.2URL改寫

URL改寫是把一些標識會話的數據(會話標識)附加到每個URL的后面,服務器每次處理請求的時候都要讀取會話標識并把它和對應的會話數據關聯起來。

使用URL改寫需要程序實現者在服務器端生成會話標識,并附加到返回給客戶端的URL的后面。這樣服務器端的程序要進行許多簡單但單調冗長的處理。另外,還必須十分小心地保證每個URL后面都附加了必要的信息。

URL是通過使用HTTPGET

構造的,它可能包含幾對參數和值。格式如下:http://localhost:8080/myweb/customer?uid=1008&name=zhangwei&

其中,uid=1008&name=zhangwei用來標識該用戶,每次該用戶的請求都會多發(fā)送兩個參數uid=1008&name=zhangwei,通過這兩個參數可以檢索該用戶關聯的其它數據。

URL改寫是一種好的解決方案,特別是在用戶禁用Cookie(見后)的情況下,它是最佳解決方案,但要考慮到以下問題:必須確保將信息附加到每個引用的網站的URL;附加參數帶來了隱私問題,也許不希望所跟蹤的實際數據是可見的;用戶可以離開會話并使用書簽返回,會丟失會話信息。

5.4.3隱藏表單域

HTML表單中可以包含下面這樣的輸入域:<inputtype="hidden"name="session"value="...">。這意味著,當表單被提交時,隱藏域的名字和數據也被包含到GET或POST數據里,我們可以利用這一機制來維持會話信息。

隱藏式表單字段存儲關于會話的信息。稍后可以使用HTTPServletRequest對象檢索隱藏的數據。提交表單時,數據包括在Get

或Post

請求中。

5.4.4Cookie

Cookie也是會話跟蹤的最常用方法,Cookie是Web服務器發(fā)送給Web瀏覽器的內容較小的純文本信息,以文本文件的形式存放在客戶端的計算機中,這些Cookie一般用于保存用戶的訪問狀態(tài),當用戶再次訪問同一個網站的時候,瀏覽器會將這些Cookie信息發(fā)送回服務器,使得服務器能夠恢復用戶上一次的訪問狀態(tài)。使用Cookie的根本目的是為了在用戶訪問期間實現不同頁面之間的數據傳輸,以解決HTTP無狀態(tài)的問題。

1、Cookie的工作原理客戶的HTTP請求到達服務器。服務器創(chuàng)建Cookie,并作為響應頭域的一部分返回用戶。瀏覽器收到包含Cookie的響應后,會把Cookie的內容用“關鍵字/值”對的形式寫入到一個客戶端專為存放Cookie的文本文件中。瀏覽器會把Cookie及隨后產生的請求發(fā)給相同的服務器。服務器可以再次讀取Cookie中存放的Cookie。 在程序實現的時候,可以對Cookie的有效期進行設置,過期的Cookie瀏覽器不會再發(fā)送給服務器。

2、Cookie類的方法

getValue/setValue

獲取/設置Cookie的值。

getMaxAge/setMaxAge

獲取/設置Cookie過期之前的時間,以秒計。如果不設置該值(默認值為-1),則Cookie只在當前會話內有效,即在用戶關閉瀏覽器之前有效,而且這些Cookie不會保存到磁盤上。getComment/setComment

用來獲取/設置Cookie的注釋。getName/setName

獲取/設置Cookie的名字。由于HttpServletRequest的getCookies方法返回的是一個Cookie對象的數組,因此通常要用循環(huán)來訪問這個數組查找特定名字,然后用getValue檢查它的值。getPath/setPath

獲取/設置Cookie適用的路徑。如果不指定路徑,Cookie將返回給當前頁面所在目錄及其子目錄下的所有頁面。這里的方法可以用來設定一些更一般的條件。例如,someCookie.setPath("/"),此時服務器上的所有頁面都可以接收到該Cookie。getSecure/setSecure

獲取/設置一個boolean值,該值表示是否Cookie只能通過加密的連接(即SSL)發(fā)送。getVersion/setVersion

獲取/設置Cookie所遵從的協(xié)議版本。

3、Cookie的使用

在程序實現的時候,要把Cookie發(fā)送到客戶端,Servlet先要調用newCookie(name,value)用合適的名字和值創(chuàng)建一個或多個Cookie,通過Cookie.setXXX設置各種屬性,通過response.addCookie(cookie)把Cookie加入應答頭。

要從客戶端讀入Cookie,Servlet應該調用request.getCookies(),getCookies()方法返回一個Cookie對象的數組。在大多數情況下,程序實現者需要用循環(huán)訪問該數組的各個元素尋找指定名字的Cookie,然后對該Cookie調用getValue方法取得與指定名字關聯的值。

創(chuàng)建Cookie

調用Cookie對象的構造函數可以創(chuàng)建Cookie。Cookie對象的構造函數有兩個字符串參數:Cookie名字和Cookie值。名字和值都不能包含空白字符以及下列字符:

[]()=,"/?@:;

創(chuàng)建和設置Cookie屬性

把Cookie加入待發(fā)送的應答頭之前,可以查看或設置Cookie的各種屬性。如在應答頭中設置Cookie,Cookie可以通過HttpServletResponse的addCookie方法加入到Set-Cookie應答頭。如下:

CookieuserCookie=newCookie("user","zhang");response.addCookie(userCookie);讀取Cookie屬性 從客戶端讀取Cookie時調用的是HttpServletRequest的getCookies方法。該方法返回一個與HTTP請求頭中的內容對應的Cookie對象數組。得到這個數組之后,一般是用循環(huán)訪問其中的各個元素,調用getName檢查各個Cookie的名字,直至找到目標Cookie。然后對這個目標Cookie調用getValue,根據獲得的結果進行其他處理。

上述處理過程在實際程序實現中會經常會遇到,為使用方便,可以實現一個較通用的getCookieValue方法。只要給出Cookie對象數組、Cookie名字和默認值,getCookieValue方法就會返回匹配指定名字的Cookie值,如果找不到指定Cookie,則返回默認

溫馨提示

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

評論

0/150

提交評論