第3章 Servlet基礎最終版_第1頁
第3章 Servlet基礎最終版_第2頁
第3章 Servlet基礎最終版_第3頁
第3章 Servlet基礎最終版_第4頁
第3章 Servlet基礎最終版_第5頁
已閱讀5頁,還剩37頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第3章Servlet基礎3.1Servlet和JSP3.2Tomcat服務器原理3.3Servlet的編寫3.4Servlet處理請求與響應3.5中文傳輸亂碼問題3.6Servlet生成HTML頁面3.7本章小結(jié)

課后習題

Web服務器接收到一個HTTP請求,處理完畢后會向客戶端返回一個HTTP響應。Web服務器接收客戶端的請求有兩種:一種是靜態(tài)頁面請求,客戶端請求的頁面中沒有動態(tài)的內(nèi)容需要處理,這些靜態(tài)的頁面直接作為響應返回。此時只需要能夠解析HTTP協(xié)議的Web服務器(如Nginx、Apache、IIS等)即可。

第二種是動態(tài)請求,客戶端所請求的頁面,需要在服務器端委托給一些應用程序進行處理,從而形成動態(tài)頁面,最后作為HTTP響應返回。此時需要服務器不僅能處理HTTP協(xié)議,還需要具備處理這些動態(tài)請求的能力,這種服務器稱作Web應用服務器。之前示例中使用的Tomcat,就是能夠處理Servlet以及JSP動態(tài)頁面的服務器,或者稱之為JavaWeb容器。3.1Servlet和JSP

Servlet以及JSP頁面都是運行在服務器上的程序,并能生成動態(tài)的內(nèi)容返回客戶端,那么二者有什么聯(lián)系和區(qū)別呢?從技術產(chǎn)生的先后順序看,Servlet技術在前,JSP技術在后。在早期的Web應用系統(tǒng)中,動態(tài)請求是由Web服務器轉(zhuǎn)發(fā)給CGI(CommonGatewayInterface,公共網(wǎng)關接口)程序進行處理的,CGI處理完畢后將結(jié)果拼接成HTML格式的文檔,并返還給Web服務器,再通過Web服務器將響應返回給用戶。

CGI程序一般由C、C++、Perl或者其他腳本語言編寫,但對于每一個客戶端的請求,CGI都開啟一個新的進程進行處理,對于服務器而言負擔較重,執(zhí)行效率低。因此Sun公司推出了基于Java的Servlet技術,Servlet本質(zhì)上來說是一個Java類,可以運行在Tomcat這樣的容器中。對于用戶的請求,Servlet以線程的形式進行處理,執(zhí)行效率更高,同時功能更為強大,對于HTML請求數(shù)據(jù)的提取和處理、會話跟蹤、Cookie設置等都有對應的方法。3.1Servlet和JSP

Servlet雖然在處理請求上非常方便,但是對于響應結(jié)果的顯示卻仍然采用CGI的方法,通過代碼打印輸出的方式去拼接HTML文檔,導致如果想生成較為復雜的頁面,代碼量將急劇增加,同時也不便于頁面整體效果的展示。因此Sun公司提出了JSP技術,采用HTML模板+嵌入Java代碼以及標簽的形式,能夠簡化響應頁面輸出的代碼量,不過JSP的底層實現(xiàn)仍是基于Servlet。

在項目Chapt_01中,第一次訪問index.jsp頁面后,該JSP頁面編譯為對應的Servlet類。Servlet類存放在Tomcat服務器的work目錄下,路徑為\apache-tomcat-9.0.33\work\Catalina\localhost\Chapt_01\org\apache\jsp。可以發(fā)現(xiàn)index.jsp已經(jīng)被轉(zhuǎn)化為一個Java類,同時也生成了對應class字節(jié)碼文件,以后再訪問index.jsp頁面,直接讀取字節(jié)碼文件即可。3.1Servlet和JSP圖3-1JSP頁面編譯為對應的Servlet類

JSP頁面通過模板的形式方便了頁面內(nèi)容的輸出,但如果JSP頁面中混雜了過多的Java代碼,將處理業(yè)務邏輯的部分都放在頁面中,同樣導致了代碼量過大,且不利于開發(fā)人員去編寫和維護。因此由于兩種技術各有其長處,JSP技術的出現(xiàn)并沒有取代Servlet,二者可以并存合作,在開發(fā)中可以發(fā)揮各自的優(yōu)勢。由于Servlet更偏向于底層的實現(xiàn),因此本書先講解Servlet技術的原理,然后再介紹JSP的使用。3.1Servlet和JSP

Tomcat是一個基于組件的Web應用服務器,在2.1.2小節(jié)曾介紹過Tomcat服務器的目錄結(jié)構(gòu),在安裝目錄下的conf文件夾下,server.xml文件是整個Tomcat服務器的配置文件。3.2Tomcat服務器原理<Serverport="8005"shutdown="SHUTDOWN">

<Listener/>….<Listener/>

<GlobaNamingResources>….</GlobaNamingResources>

<Servicename="Catalina">

<Connectorport="8080"protocol="HTTP/1.1"redirectPort="8443"/>

<EnginedefaultHost="localhost"name="Catalina">

<HostappBase="webapps"autoDeploy="true"name="localhost"><ContextdocBase="Chapt_01"path="/Chapt_01"reloadable="true"

source="org.eclipse.jst.jee.server:Chapt_01"/><ContextdocBase="Chapt_02"path="/Chapt_02"reloadable="true"

source="org.eclipse.jst.jee.server:Chapt_02"/>

</Host></Engine>

</Service></Server>3.2.1 Tomcat體系結(jié)構(gòu)server.xml文件中的標簽元素(為了方便講解,只列出了主要的組件節(jié)點),大致結(jié)構(gòu)如下3.2.1 Tomcat體系結(jié)構(gòu)配置文件中的根節(jié)點是Server,代表頂級服務器。該節(jié)點包含了port="8005"shutdown="SHUTDOWN"兩個屬性,表示服務器通過8005端口號監(jiān)聽和關閉Tomcat服務器的請求。Server節(jié)點下包含若干個Listener、GlobaNamingResources和Service等子節(jié)點。(1)Listener節(jié)點。該節(jié)點表示服務器運行時狀態(tài)監(jiān)聽的配置,主要監(jiān)聽服務器是否會內(nèi)存泄漏、線程安全以及日志等信息。(2)GlobaNamingResources節(jié)點。該節(jié)點表示全局資源的配置,比如指定Tomcat服務器用戶信息,這些信息存放在conf目錄下的tomcat-users.xml文件中。(3)Service節(jié)點。該節(jié)點表示對外提供的應用服務,至少存在一個默認名稱為Catalina的Service節(jié)點。Service節(jié)點又包含若干個Connector和一個Engine組件。① Connector:Tomcat服務器的核心組件,負責客戶端交互的連接器組件,負責接

收用戶請求并交給Engine組件處理,以及將處理完畢后的響應返還給客戶??梢?/p>

有多個Connector,并設置該Connector用來接收客戶請求的端口號(如默認的8080),采用的HTTP協(xié)議版本,以及HTTPS協(xié)議轉(zhuǎn)發(fā)端口號等。② Engine:Tomcat服務器的核心組件,負責處理用戶請求的組件,有defaultHost和name兩個屬性值,其中defaultHost表示默認的虛擬主機名稱。工作的該組件下又

包含若干Host元素和Realm元素。至少有一個Host元素的name屬性和Engine的

defaultHost值對應。在Host元素下的ContextdocBase元素則定義了一個實際的

Web項目。Relam元素則用于安全管理的配置,一般與tomcat-uesrs.xml配合使用。3.2.2

Tomcat核心組件

Tomcat可以根據(jù)需求,通過設置不同的監(jiān)聽端口配置多個Connector,當連接器指定的端口號監(jiān)聽到客戶端發(fā)送過來的TCP請求后,將分別創(chuàng)建一個request和response對象,然后新建一個線程,將request和response對象傳送給Engine組件,并等待處理結(jié)果,獲得response后,將響應返還給客戶端。Engine組件可以指定多個虛擬主機Host組件,Host可以配置以下3個屬性。(1)appBase屬性。Web項目的部署路徑,在2.1.2小節(jié)中設置在webapps路徑下。(2)autoDeploy屬性。項目是否自動部署,取值為ture或者false,ture表示自動。(3)name屬性。虛擬主機名稱,取值localhost表示本機,剛好對應Engine元素的defaultHost的取值。3.2.2

Tomcat核心組件在Host組件下又可以具體指定Context組件,實際上對應著已經(jīng)在Tomcat服務器下運行的Web項目。每當有新的項目部署到服務器時,都會在Host組件下生成一個新的Context元素進行配置。例如<ContextdocBase="Chapt_01"path="/Chapt_01"reloadable="true"source="org.eclipse.jst.jee.server:Chapt_01"/>docBase屬性設置了Chapt_01項目的根目錄、path屬性表示項目訪問的路徑,即http://localhost:8080/Chatp_01/xxx。reloadable=true表示服務器會檢測項目文件的變動,tomcat服務器在運行狀態(tài)下會監(jiān)視WEB-INF/classes和WEB-INF/lib目錄下class文件的改動,如果監(jiān)測到class文件有變動,服務器會自動重新加載Web應用。

Context組件實際上就是運行Servlet的基礎容器,當用戶訪問該Web應用項目時,所有的請求都需要到該Context環(huán)境下(即該項目下)去尋找對應的Servlet類去處理。3.3Servlet的編寫

本節(jié)介紹在Eclipse中編寫Servlet并運行,以及Servlet運行機制、重要方法以及生命周期。3.3.1

Servlet的創(chuàng)建

在Eclipse中新建一個名為Chap_03的動態(tài)Web項目,由于Servlet是一個Java類,所以不同于JSP頁面是放到項目的WebContent下,Servlet類需要在項目的src目錄下去建立,因此在src目錄下新建一個com.test.servlet的包。下面介紹在Eclipse中通過模板創(chuàng)建Servlet的步驟。(1)鼠標右擊com.test.servlet包,在彈出的菜單中依次選擇New→Other,在選項卡中,找到Web組件下的Servlet選項,選擇新建Servlet類。如圖3-2所示。(2)Servlet命名。如圖3-3所示。(3)Servlet參數(shù)設置。如圖3-4所示。(4)選擇Servlet重寫方法。如圖3-5所示。圖3-2新建Servlet類圖3-3Servlet命名圖3-4Servlet參數(shù)設置圖3-5選擇Servlet重寫方法3.3.1

Servlet的創(chuàng)建

此時在項目下,已經(jīng)生成了FirstServlet類。該類引入了javax.servlet.http包中的一些類。除了父類HttpServlet類以外,還包括HttpServletRequest以及HttpServletResponse,分別表示請求和響應,它們的實例化對象request和response作為doGet和doPost方法的參數(shù)。

此外FirstServlet類還引入了javax.servlet.annotation.WebServlet類,這個類是用于注解的類,可以看到在FirstServlet類上包含有@WebServlet("/FirstServlet")的一行注解代碼。

這是因為在新建項目時選擇的Dynamicwebmoduleversion為3.1,因此項目采用的是Servlet3.1規(guī)范,在Servlet3.0以上版本中,默認是使用注解對Servlet進行配置。@WebServlet("/FirstServlet")這條注解語句,其實對應了在新建FirestServlet時配置的URLMapping。3.3.1

Servlet的創(chuàng)建

如果項目選擇的是Servlet2.5及以下版本,則在Servlet新建后,需要在項目的web.xml配置文件的<web-app>節(jié)點下,編寫如下代碼完成FirstServlet的配置。<servlet><servlet-name>FirstServlet</servlet-name><servlet-class>com.test.servlet.FirstServlet</servlet-class></servlet><servlet-mapping><servlet-name>FirstServlet</servlet-name><url-pattern>/FirstServlet</url-pattern></servlet-mapping>

其中servlet節(jié)點下有servlet-name和servlet-class兩個元素,其值分別對應Servlet設置的名稱和對應的具體類,servlet-mapping節(jié)點下有servlet-name和url-pattern兩個元素,配置了FirstServlet的訪問路徑。3.3.1

Servlet的創(chuàng)建通過模板創(chuàng)建Servlet,只需要在界面中設置參數(shù),Eclipse就會自動生成對應的配置信息。無論采用注解還是在web.xml中配置,效果都是等同的。而且相同的Servlet配置只能選取一種方式,重復配置將會報錯。當然也可以采用手動的方式進行編寫和修改,此時需要注意對應的配置語法和格式。3.3.2Servlet的運行在創(chuàng)建完FirstServlet以后,進行如下操作運行Servlet。(1)右擊Chapt_03項目,選擇RunAs->RunonServer,選擇Tomcat9服務器,單擊Finish按鈕,此時Chapt_03項目被部署到服務器中。(2)打開瀏覽器,輸入網(wǎng)址http://localhost:8080/Chapt_03/FirstServlet。運行效果如圖3-6。圖3-6FirstServlet運行效果3.3.2Servlet的運行Tomcat服務器按照以下步驟進行處理。(1)該請求中使用端口號為8080,因此會被一直監(jiān)聽8080端口號的Connector組件獲取。(2)Connector組件把請求交給Engine組件處理,并等待回應。(3)Engine查找Host組件,找到匹配名字為localhost的虛擬主機。(4)在localhost主機上,查找Context組件,匹配到名字為Chapt_03的應用。(5)根據(jù)請求路徑/FirstServlet,在Chapt_03下查找URLMapping配置,找到對應的FirstServlet類去處理。(6)構(gòu)造HttpServletRequest對象和HttpServletResponse對象,作為參數(shù)傳送給FirstServlet的doGet()方法,處理完畢后,將結(jié)果封裝到HttpServletResponse對象中。(7)Context將HttpServletResponse響應返回給Host。(8)Host將響應返回給Engine。(9)Engine將響應返回給Connector。(10)Connector將響應結(jié)果返回給瀏覽器客戶端。3.3.2Servlet的運行

最終頁面的顯示結(jié)果是來自FirstServlet的doGet()方法,在方法體內(nèi)部只有一條語句:response.getWriter().append("Servedat:").append(request.getContextPath());response對象的getWriter()方法獲取了一個輸出流對象,向客戶端進行文本的輸出,后面的append方法表示文本的追加輸出,第二個append方法里的參數(shù),由request對象通過getContextPath()方法獲取,表示請求的上下文Context對象路徑,即/Chapt_03。因此最終輸出為Servedat:/Chapt_03。3.3.3Servlet的運行機制

當Servlet運行后,最終也會編譯成字節(jié)碼文件,存放在Tomcat服務器對應項目目錄下,F(xiàn)irstServlet的字節(jié)碼文件可以在Chapt_03\WEB-INF\classes\com\test\servlet\路徑下找到。那么當每次運行Servlet時,都會創(chuàng)建一個實例化對象嗎?實際上在默認情況下,Servlet是以單例多線程的形式運行的,下面通過例3-1演示Servlet運行狀態(tài)?!纠?-1】Servlet運行狀態(tài)示例。在Chapt_03項目下再新建一個名為SecondServlet的Servlet類,通過注解@WebServlet(“/SecondServlet”),設置其映射路徑為/SecondServlet,然后在其構(gòu)造函數(shù)和doGet方法中編寫相應代碼。3.3.3Servlet的運行機制

注意新建Servlet或者JSP需要重啟服務器,項目重新部署后才能訪問。為模擬不同客戶端訪問同一個Servlet的場景,首先通過Firefox瀏覽器訪問SecondServlet,然后觀察Eclipse的Console輸出內(nèi)容。

首次運行SecondServlet后的輸出結(jié)果,如圖3-7所示。

在不關閉服務器的情況下,使用Google瀏覽器,再次訪問SecondServlet后的輸出結(jié)果如圖3-8所示。圖3-7首次運行SecondServlet后的輸出結(jié)果圖3-8再次訪問SecondServlet后的輸出結(jié)果

由此可見,只有第一次訪問Servlet時,運行了構(gòu)造函數(shù)和doGet方法,第二次訪問只執(zhí)行了doGet方法,因此只有第一次運行時創(chuàng)建了對象,再次訪問時并沒有再次實例化對象。3.3.4Servlet方法與生命周期

1.Servlet方法在利用模板新建一個Servlet類時,默認需要繼承HttpServlet這個抽象類。HttpServlet又是繼承于GenericServlet這個抽象類,而GenericServlet抽象類又實現(xiàn)了Servlet以及ServleConfig兩個接口。因此Servlet可以繼承或者重寫一些父類方法,這些方法將伴隨著Servlet的整個生命周期。(1)init(ServletConfigconfig):該方法繼承與GenericServlet類,是實現(xiàn)了Servlet接口聲明的init方法。該方法在Servlet類被加載后被調(diào)用,ServletConfig接口對象作為參數(shù)傳遞進來,從而可以獲取一些初始化參數(shù)。如果有特殊初始參數(shù)配置方面的需求,可以重寫該方法。(2)service(HttpServletRequestrequest,HttpServletResponseresponse):該方法根據(jù)request對象的getMethod方法獲取請求采用的方式,再去調(diào)用對應的doXXX方法。(3)doXXX(HttpServletRequestrequest,HttpServletResponseresponse):包括doGet、doPost、doPut、doDelete、doHead、doTrace、doOptions方法。這些方法處理不同請求方式的HTTP請求。(4)destroy():當Servlet消亡時會調(diào)用該方法。當有特殊需求時,比如需要清理某些設置及參數(shù)時可以重寫該方法。3.3.4Servlet方法與生命周期

2.Servlet生命周期Servlet的生命周期過程:從第一次加載時調(diào)用init方法,接著調(diào)用service方法獲取請求采用的方式,然后調(diào)用對應的doXXX方法,執(zhí)行該方法完畢后返回響應的結(jié)果。當Servlet要消亡時(如關閉了服務器),則調(diào)用destroy方法。在實際開發(fā)中,一般只需要根據(jù)請求方式重寫對應的doXXX()方法即可。其中使用最多的是doGet和doPost方法,分別處理GET和POST類型的請求。3.4Servlet處理請求與響應本節(jié)介紹在Servlet處理請求與響應時方法的使用,各種類型數(shù)值的獲取與處理。3.4.1doGet與doPost方法doGet和doPost方式分別處理GET和POST兩種發(fā)送方式的請求,兩種方法的應用場景有所區(qū)別。GET方式一般針對頁面及資源的請求。如訪問超鏈接、或者通過URL進行參數(shù)傳值,以及表單默認的提交,均采用GET方式進行請求。POST方式一般用于向服務器提交數(shù)據(jù),例如當表單method屬性設置為POST時,則表單采用POST方式進行提交。GET方式傳遞的值直接放在請求行中,與網(wǎng)址內(nèi)容一起進行編碼。

POST傳遞的值則放在請求體中。doGet和doPost方法都包含HttpServletRequest和HttpServletResponse類型的參數(shù),通過request對象獲取請求參數(shù),進行處理后,再利用response對象返回響應。在編寫代碼時,只用在doGet方法體內(nèi)編寫處理請求的代碼即可,然后在doPost方法內(nèi),調(diào)用doGet方法。3.4.2rqequest基本信息的獲取request對象提供了下面的方法用于獲取請求中的一些重要信息。(1)StringgetMethod():獲取請求方式,比如GET或者POST。(2)StringgetRequestURI():獲取請求的URI(UniformResourceIdentifier,統(tǒng)一資源標志符)。(3)StringgetProtocol():獲取請求采用的協(xié)議。(4)StringgetServerPort():獲取請求服務器端口號。(5)StringgetServerName():獲取請求服務器的名稱。(6)StringgetContextPath():獲取請求的上下文路徑。(7)StringgetRemoteAddr():獲取發(fā)送請求的客戶端IP地址。以上信息在某些應用場景中需要用到,例如獲取上下文路徑可以用于絕對地址的拼接,而獲取客戶端IP地址則可以記錄請求日志信息,甚至可以設置黑名單禁用部分IP地址。下面通過例3-2演示request對象基本信息的獲取。3.4.2rqequest基本信息的獲取

【例3-2】request對象基本信息的獲取。

新建一個Servlet類,取名為RequestInfoServlet,通過注解@WebServlet("/RequestInfoServlet")設置映射路徑為/RequestInfoServlet,然后在doGet方法中編寫代碼。RequestInfoServlet的doGet方法中使用了request的相應方法獲取基本信息。訪問RequestInfoServlet后,request對象的基本信息,如圖3-9所示。圖3-9request對象的基本信息3.4.2rqequest基本信息的獲取Servlet輸出時利用response對象使用getWriter或者getOutputStream()方法獲取輸出流,二者互斥不能混用。例子中使用的PrintWriter對象用于向客戶端輸出字符流,包括以下5個常用的方法。(1)voidprint():輸出文本信息后不換行。(2)voidprintln():輸出文本信息后換行。(3)voidappend():和print類似,但方法可以直接追加,本例中即采用此方法,因此在相應變量后添加了\r\n進行換行操作。(4)voidflush():輸出緩沖區(qū)數(shù)據(jù),在客戶端輸出后清除緩沖區(qū)數(shù)據(jù)。(5)voidclose():關閉輸出流。3.4.3URL傳值數(shù)據(jù)的獲取

超鏈接是網(wǎng)頁中常見的元素,單擊超鏈接可以跳轉(zhuǎn)到指定的URL,該地址可以是服務器外部網(wǎng)址,也可以是服務器內(nèi)部地址。同時超鏈接后面可以附帶參數(shù)一同發(fā)送給服務器,從而實現(xiàn)頁面之間信息的傳遞。單擊超鏈接是通過GET方式提出請求,下面通過例3-2演示通過超鏈接進行URL傳遞參數(shù),服務器通過Servlet獲取后再輸出到客戶端頁面中。3.4.3URL傳值數(shù)據(jù)的獲取

【例3-3】通過超鏈接進行URL傳遞參數(shù)。(1)在項目的WebContent下新建一個HTML頁面,取名為hyperlink.html,在body標簽體內(nèi)部添加一個超鏈接,代碼如下所示。<ahref=URLServlet?a=hello&b=world>通過超鏈接進行URL傳值</a>該超鏈接指向URLServlet,超鏈接指向的URL后面附帶兩個參數(shù),訪問hyperlink.html頁面,如圖3-10所示。圖3-10訪問hyperlink.html頁面注意超鏈接的href地址前沒有加"/"反斜杠,表示采用的是相對路徑,訪問的是/Chapt_03/路徑下的URLServlet。如果地址前加上了反斜杠,則表示使用的是絕對地址,此時必須加上項目路徑/Chapt_03/,代碼如下所示。<ahref=/Chapt_03/URLServlet?a=hello&b=world>通過超鏈接進行URL傳值</a>訪問路徑的寫法是初學時容易犯錯的地方,尤其是超鏈接的href屬性以及表單提交的action的寫法,如果路徑有誤,則頁面會報404錯誤,此時應排查采用的是相對還是絕對路徑。3.4.3URL傳值數(shù)據(jù)的獲?。?)新建一個Servlet,取名為URLServlet,通過注解@WebServlet(“/URLServlet”)設置映射路徑為/RequestInfoServlet,然后在doGet方法中編寫相應代碼。單擊hyperlink.html中的超鏈接,頁面跳轉(zhuǎn)到URLServlet,獲取超鏈接獲取URL傳遞的參數(shù),如圖3-11所示。圖3-11獲取超鏈接和URL傳遞的參數(shù)此時參數(shù)附加在了URL后面,并出現(xiàn)在了地址欄中,說明超鏈接的確是通過GET方式進行的請求。在URLServlet類的doGet方法中,使用了request對象的getParameter(Stringname)方法。該方法的作用就是通過參數(shù)名來獲取對應的參數(shù)值。該方法使用較為頻繁,在獲取表單提交的數(shù)據(jù)時也會采用。3.4.4表單中單值元素數(shù)據(jù)的獲取

表單提交是Web應用中常見的功能,本節(jié)介紹Servlet處理表單中單一元素數(shù)據(jù)的方法。單值元素是指該表單元素提交數(shù)據(jù)給服務器時,只包含1個變量。表單中的單值元素包括:文本框、密碼框、單選按鈕、下拉框以及多行文本框等。下面通過例3-4演示Servlet獲取表單中單值元素的數(shù)據(jù)并處理?!纠?-4】Servlet獲取表單中單值元素的數(shù)據(jù)。(1)新建一個HTML頁面,取名為single.html,在body標簽體內(nèi)部編寫一個包含上述元素的表單。(2)然后新建GetSingleServlet,通過注解@WebServlet(“/GetSingleServlet”)設置映射路徑為/GetSingleServlet,在doGet方法中編寫相應代碼。(3)打開瀏覽器訪問single.html并填寫表單數(shù)據(jù),如圖3-12所示。單擊“提交”按鈕將表單數(shù)據(jù)提交給GetSingleServlet處理,獲取單值元素并輸出到頁面,如圖3-13所示。圖3-12訪問single.html并填寫表單數(shù)據(jù)圖3-13獲取單值元素并輸出到頁面3.4.5表單中多值元素數(shù)據(jù)的獲取

表單中如果有多個元素的name屬性值相同,當表單提交時,這些同名元素將以數(shù)組的形式向服務器發(fā)送數(shù)據(jù),這樣的元素稱為多值元素。典型的多值元素包括:復選框、多選列表框以及其他同名元素組合。下面通過例3-5演示Servlet獲取表單中多值元素的數(shù)據(jù)并處理?!纠?-5】Servlet獲取表單中多值元素的數(shù)據(jù)并處理。(1)新建一個HTML頁面,取名為multiple.html,在body標簽體內(nèi)部編寫一個包含上述元素的表單。(2)新建一個Servlet類,取名為GetMultipleServlet,通過注解@WebServlet(“/GetMultipleServlet”)設置映射路徑為/GetMultipleServlet,在doGet方法中編寫相應代碼。(3)打開瀏覽器,訪問multiple.html頁面并填寫表單數(shù)據(jù),如圖3-14所示。打開瀏覽器,訪問multiple.html頁面并填寫表單數(shù)據(jù),如圖3-15所示。圖3-14訪問multiple.html頁面并填寫表單數(shù)據(jù)圖3-15獲取多值元素并輸出到頁面3.5中文傳輸亂碼問題例3-4演示了Servlet處理表單的操作,URL傳值以及表單提交的數(shù)據(jù)都是英文和數(shù)值。如果提交的表單數(shù)據(jù)是中文,是否能正確顯示呢?圖3-16表單輸入中文數(shù)據(jù)并提交圖3-17獲取POST方式提交的中文參數(shù)圖3-18獲取GET方式提交的中文參數(shù)

實際上,參數(shù)是由客戶端發(fā)出request,到服務器由Servlet處理,然后response輸出到客戶端顯示。之所以出現(xiàn)亂碼,是由于中文參數(shù)在request、response以及最終客戶端瀏覽器編碼的方式不同造成的。重新訪問single.html頁面,表單輸入中文數(shù)據(jù)并提交,如圖3-16所示。

跳轉(zhuǎn)到Servlet處理后,獲取POST方式提交的中文參數(shù),出現(xiàn)中文亂碼,如圖3-17所示。

如果提交方式為GET,同樣出現(xiàn)了中文參數(shù)亂碼問題,如圖3-18所示。3.5.1請求參數(shù)編碼下面分GET和POST兩種方式討論請求參數(shù)的編碼問題。(1)GET方式傳遞的參數(shù)時放在HTTP請求行中,并與網(wǎng)址內(nèi)容一起進行編碼后,再傳遞給服務器進行處理。在Tomcat服務器中有一個名為URICoding的參數(shù),即用于指定其請求地址的編碼方式。在Tomcat8以上版本中這個參數(shù)的默認值是UTF-8,由于UTF-8編碼支持中文,因此通過GET方式傳遞參數(shù)到服務器并打印不會出現(xiàn)亂碼的情況。在GetSingleServlet中添加如下代碼,用于打印request傳遞參數(shù)到服務器后內(nèi)容。System.out.println(username);System.out.println(information);重新提交表單,在Console中可以看到中文參數(shù)顯示正常沒有亂碼。中文參數(shù)通過GET方式傳遞到服務器,如圖3-19所示。圖3-19中文參數(shù)通過GET方式傳遞到服務器3.5.1請求參數(shù)編碼

在Tomcat7及以下版本中,這個參數(shù)默認為ISO8859-1,可以通過修改server.xml文件中Connector組件部分的配置,修改默認編碼方式。<ConnectorconnectionTimeout="20000"port="8080"protocol="HTTP/1.1"redirectPort="8443"URIEncoding="UTF-8"/>如果不修改服務器的URICoding編碼方式,則需要對GET方式傳遞的每個參數(shù)都單獨轉(zhuǎn)換編碼格式,例如:Stringusername=newString(request.getParameter("username").getBytes("ISO-8859-1"),"utf-8");3.5.1請求參數(shù)編碼

(2)將表單提交方式修改為POST方式,重新提交表單,還是利用Console進行觀察,發(fā)現(xiàn)此時出現(xiàn)中文亂碼。中文參數(shù)通過POST方式傳遞到服務器,如圖3-20所示。

圖3-20中文參數(shù)通過POST方式傳遞到服務器由于POST方式提交的數(shù)據(jù)是存放在HTTP的請求體中,而服務器對POST請求的數(shù)據(jù)編碼的默認方式不是UTF-8,因此在服務器端打印中文亂碼??梢灾匦轮付ǚ掌鲗φ埱篌w的編碼方式來避免上述問題,修改GetSingleServlet類的代碼,在使用getParameter方法獲取參數(shù)前,加上如下一行代碼,用于指定POST方式提交參數(shù)的編碼格式。request.setCharacterEncoding("utf-8");然后重新提交表單,此時后臺打印中文參數(shù)顯示正常。3.5.2響應編碼

當Servlet處理完畢后,通過response對象進行中文的輸出時,服務器也有默認的編碼方式,可以通過response.getCharacterEncoding()獲取,同時也提供了setCharacterEncoding()方法用于更改編碼方式。在GetSingleServlet類中,添加如下代碼。//獲取response默認編碼System.out.println(response.getCharacterEncoding());//設置Tomcat的response

溫馨提示

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

評論

0/150

提交評論