官术网_书友最值得收藏!

理論篇

第1章 Servlet基礎(chǔ)

本章目標(biāo)

■ 了解動態(tài)網(wǎng)站開發(fā)的相關(guān)技術(shù)

■ 理解Servlet的運行原理及生命周期

■ 掌握Servlet的編寫及部署

■ 掌握Servlet對表單數(shù)據(jù)的處理

■ 掌握Servlet對HTTP請求報頭的處理

學(xué)習(xí)導(dǎo)航

任務(wù)描述

【描述1.D.1】

使用Servlet輸出“Hello World”頁面。

【描述1.D.2】

使用Servlet處理表單數(shù)據(jù),當(dāng)用戶提交的數(shù)據(jù)正確時(用戶名haier,密碼soft),輸出“登錄成功!”,否則提示“登錄失??!”。

【描述1.D.3】

使用request對象讀取報頭信息,并打印在頁面中。

【描述1.D.4】

通過設(shè)置響應(yīng)報頭,實現(xiàn)動態(tài)時鐘。

【描述1.D.5】

使用請求重定向和轉(zhuǎn)發(fā)兩種方式,使用戶自動訪問重定向后的頁面,區(qū)分轉(zhuǎn)發(fā)和重定向的區(qū)別。

1.1 動態(tài)網(wǎng)站技術(shù)概述

在《Web編程基礎(chǔ)》課程中已經(jīng)學(xué)習(xí)使用HTML、CSS、JavaScript等相關(guān)技術(shù)來建設(shè)靜態(tài)網(wǎng)站,其中,靜態(tài)網(wǎng)頁文件的擴(kuò)展名為“.htm”或“.html”,這些頁面不能與服務(wù)器進(jìn)行數(shù)據(jù)交互。隨著站點內(nèi)容和功能需求的不斷復(fù)雜化,單一的靜態(tài)網(wǎng)站技術(shù)往往不能滿足應(yīng)用的要求。例如,靜態(tài)網(wǎng)站無法完成將數(shù)據(jù)傳輸?shù)椒?wù)器上進(jìn)行處理并存儲到數(shù)據(jù)庫中,此時就需要動態(tài)網(wǎng)站技術(shù)。

1.1.1 動態(tài)網(wǎng)站技術(shù)

動態(tài)網(wǎng)站并不是指具有動畫功能的網(wǎng)站,而是指基于數(shù)據(jù)庫架構(gòu)的網(wǎng)站,一般由大量的動態(tài)網(wǎng)頁(如JSP)、后臺處理程序(如Servlet)和用于存儲內(nèi)容的數(shù)據(jù)庫組成。所謂“動態(tài)網(wǎng)頁”,本質(zhì)上與網(wǎng)頁上的各種動畫、滾動字幕等視覺上的“動態(tài)效果”無關(guān)。動態(tài)網(wǎng)頁可以是純文字內(nèi)容,也可以包含各種動畫內(nèi)容,這些只是網(wǎng)頁具體內(nèi)容的表現(xiàn)形式。無論網(wǎng)頁是否具有動態(tài)效果,采用動態(tài)網(wǎng)站技術(shù)生成的網(wǎng)頁都稱為動態(tài)網(wǎng)頁。

動態(tài)網(wǎng)站一般具有以下幾個特點。

交互性:網(wǎng)頁會根據(jù)用戶的要求和選擇而動態(tài)改變和響應(yīng)。例如,用戶在網(wǎng)頁中填寫表單信息并提交,服務(wù)器可以對數(shù)據(jù)進(jìn)行處理并保存到數(shù)據(jù)庫中,然后跳轉(zhuǎn)到相應(yīng)頁面。因此,動態(tài)網(wǎng)站可以實現(xiàn)用戶注冊、信息發(fā)布、訂單管理等功能。

自動更新:無須手動更新HTML文檔,便會自動生成新的頁面,大大減少了工作量。例如,在論壇中發(fā)布信息時,后臺服務(wù)器可以產(chǎn)生新的網(wǎng)頁。

隨機性:在不同的時間、不同的用戶訪問同一網(wǎng)頁時可能產(chǎn)生不同的頁面。

注意 動態(tài)網(wǎng)站一般采用動靜結(jié)合的原則:網(wǎng)站中內(nèi)容頻繁更新的,可采用動態(tài)網(wǎng)頁技術(shù);網(wǎng)站中內(nèi)容不需要更新的,則可采用靜態(tài)網(wǎng)頁進(jìn)行顯示。通常一個網(wǎng)站既包含動態(tài)網(wǎng)頁也包含靜態(tài)網(wǎng)頁。

動態(tài)網(wǎng)站技術(shù)有早期的CGI技術(shù),全名Common Gateway Interface(公用網(wǎng)關(guān)接口)。CGI提供了一種機制,可以實現(xiàn)客戶和服務(wù)器之間真正的雙向交互。這種技術(shù)為諸如在線用戶支持和電子商務(wù)等新思想的實現(xiàn)鋪平了道路,同時CGI技術(shù)因可以使用不同的語言編寫適合的CGI程序,如Visual Basic、Delphi和C/C++等,并且功能強大,被早期的很多網(wǎng)站采用。但由于編程困難、效率低下、修改復(fù)雜,所以逐漸被新技術(shù)所取代。目前被廣泛應(yīng)用的動態(tài)網(wǎng)站技術(shù)主要有以下三種。

PHP(Hypertext Preprocessor):是超文本預(yù)處理器,其語法大量借鑒了C、Java、Perl等語言,只需要很少的編程知識就能使用PHP建立一個真正交互的Web站點。由于PHP開放源代碼,并且是免費的,所以非常流行,是當(dāng)今Internet上最為火熱的腳本語言之一。

ASP(Active Server Pages):是一種類似HTML、Script與CGI結(jié)合體的技術(shù),它沒有提供自己專門的編程語言,允許用戶使用許多已有的腳本語言編寫ASP應(yīng)用程序。但ASP技術(shù)局限于微軟的操作系統(tǒng)平臺之上,主要工作環(huán)境為微軟的IIS應(yīng)用程序結(jié)構(gòu),而且ASP技術(shù)不能很容易地實現(xiàn)在跨平臺Web服務(wù)器上工作,因此一般只適合一些中小型站點。但目前由ASP升級演變而來的ASP.NET支持大型網(wǎng)站的開發(fā)。

JSP(Java Server Pages):是基于Java Servlet以及整個Java體系的Web開發(fā)技術(shù)。JSP是由SUN公司于1999年6月推出的新技術(shù),它與ASP有一定的相似之處,但JSP能在大部分的服務(wù)器上運行,而且其應(yīng)用程序易于維護(hù)和管理,安全性能方面也被認(rèn)為是這三種基本動態(tài)網(wǎng)站技術(shù)中最好的。

1.1.2 B/S架構(gòu)

在動態(tài)網(wǎng)站技術(shù)中,一般使用瀏覽器作為客戶端,當(dāng)客戶在瀏覽器中發(fā)出請求時,Web服務(wù)器得到請求后查找資源,然后向客戶返回一個結(jié)果,這就是B/S(Browser/Server)架構(gòu),如圖1-1所示。

圖1-1 B/S模型

在B/S架構(gòu)中,用戶的請求與Web服務(wù)器響應(yīng)需要通過Internet網(wǎng)絡(luò)從一臺計算機發(fā)送到另一臺計算機,不同計算機之間是使用HTTP(HyperText Transfer Protocol)協(xié)議進(jìn)行通信的。HTTP是超文本傳輸協(xié)議,包含命令和傳輸信息,不僅用于Web訪問,也可以用于其他互聯(lián)網(wǎng)/內(nèi)聯(lián)網(wǎng)應(yīng)用系統(tǒng)之間的通信,從而實現(xiàn)各種資源信息的超媒體訪問集成。

1.2 Servlet簡介

Servlet是JavaEE架構(gòu)中的關(guān)鍵組成部分。JavaEE是基于分布式和多層結(jié)構(gòu)的企業(yè)級應(yīng)用開發(fā)規(guī)范和標(biāo)準(zhǔn)。目前,在企業(yè)應(yīng)用開發(fā)中不僅會使用傳統(tǒng)的JavaEE組件(例如JDBC、Servlet、EJB等),還會使用一些輕量級的框架結(jié)構(gòu)(例如Struts、Hibernate和Spring),以提高企業(yè)開發(fā)效率。在Java企業(yè)級開發(fā)應(yīng)用中會使用到的技術(shù)如圖1-2所示。Servlet技術(shù)是Sun公司提供的一種實現(xiàn)動態(tài)網(wǎng)頁的解決方案,它是基于Java編程語言的Web服務(wù)器端編程技術(shù),主要用于在Web服務(wù)器端獲得客戶端的訪問請求信息并動態(tài)生成對客戶端的響應(yīng)信息。此外,Servlet技術(shù)也是JSP技術(shù)的基礎(chǔ)。

圖1-2 JavaEE技術(shù)組成

Servlet是Web服務(wù)器端的Java應(yīng)用程序,它支持用戶交互式地瀏覽和修改數(shù)據(jù),生成動態(tài)的Web頁面。比如,當(dāng)瀏覽器發(fā)送一個請求到服務(wù)器后,服務(wù)器會把請求送往一個特定的Servlet,這樣Servlet就能處理請求并構(gòu)造一個合適的響應(yīng)(通常以HTML網(wǎng)頁形式)返回給客戶,如圖1-3所示。

圖1-3 Servlet的作用

Servlet與普通Java程序相比,只是輸入信息的來源和輸出結(jié)果的目標(biāo)不一樣,例如,對于Java程序而言,用戶一般通過GUI窗口輸入信息,并在GUI窗口上獲得輸出結(jié)果,而對于Servlet程序而言,用戶一般通過瀏覽器輸入并獲取響應(yīng)結(jié)果。通常普通Java程序所能完成的大多數(shù)任務(wù),Servlet程序都可以完成。Servlet程序具有以下特點:

高效

在傳統(tǒng)CGI中,如果有N個并發(fā)的對同一CGI程序的請求,則該CGI程序的代碼在內(nèi)存中重復(fù)裝載了N次;而對于Servlet,處理請求的是N個線程,只需要一份Servlet類代碼。在性能優(yōu)化方面,Servlet也比CGI有著更多的選擇,比如緩沖以前的計算結(jié)果、保持?jǐn)?shù)據(jù)庫連接的活動等。

方便

Servlet提供了大量的實用工具例程,例如自動地解析和解碼HTML表單數(shù)據(jù)、讀取和設(shè)置HTTP頭、處理Cookie、跟蹤會話狀態(tài)等。

功能強大

在Servlet中,許多使用傳統(tǒng)CGI程序很難完成的任務(wù)都可以輕松地完成。例如,Servlet能夠直接和Web服務(wù)器交互,而普通的CGI程序不能。Servlet還能夠在各個程序之間共享數(shù)據(jù),很容易地實現(xiàn)數(shù)據(jù)庫連接池之類的功能。

■ 良好的可移植性

Servlet是用Java語言編寫的,所以具備Java的可移植性特點。此外,Servlet API具有完善的標(biāo)準(zhǔn),支持Servlet規(guī)范的容器都可以運行Servlet程序,例如Tomcat、Resin等。

1.3 第一個Servlet

編寫Servlet需要遵循其規(guī)范:

■ 創(chuàng)建Servlet時,需要繼承HttpServlet類,同時需要導(dǎo)入Servlet API的兩個包:javax.servlet和javax.servlet.http。javax.servlet包提供了控制Servlet生命周期所必需的Servlet接口,是編寫Servlet時必須要實現(xiàn)的;javax.servlet.http包提供了從Servlet接口派生出的專門用于處理HTTP請求的抽象類和一般的工具類。

■ 根據(jù)數(shù)據(jù)的發(fā)送方式,覆蓋doGet()、doPost()方法之一或全部。doGet()和doPost()方法都有兩個參數(shù),分別為HttpServletRequest和HttpServletResponse類型。這兩個參數(shù)分別用于表示客戶端的請求和服務(wù)器端的響應(yīng)。通過HttpServletRequest,可以從客戶端獲得發(fā)送過來的信息;通過HttpServletResponse,可以讓服務(wù)器端對客戶端做出響應(yīng),最常用的就是向客戶端發(fā)送信息。關(guān)于這兩個參數(shù),將在后續(xù)內(nèi)容中詳細(xì)講解。

注意 如果在瀏覽器中直接輸入地址來訪問Servlet資源,屬于使用GET方式訪問。

下述代碼用于實現(xiàn)任務(wù)描述1.D.1,使用Servlet輸出“Hello World”頁面。

【描述1.D.1】HelloServlet.java

    // 創(chuàng)建一個Servlet類,繼承HttpServlet
    public class HelloServlet extends HttpServlet
    {
        // 重寫doGet()
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 設(shè)置響應(yīng)到客戶端的文本類型為HTML
            response.setContentType("text/html");
            // 獲取輸出流
            PrintWriter out = response.getWriter();
            out.println(" Hello World");
        }
    }

上述代碼會向客戶端瀏覽器中打印“Hello World”信息。通過response對象的getWriter()方法可以獲取向客戶端輸出信息的輸出流:

    PrintWriter out = response.getWriter();

調(diào)用輸出流的println()方法可以在客戶端瀏覽器中打印消息。例如:

    out.println(" Hello World");

下面在Web應(yīng)用的部署文件web.xml中注冊此Servlet信息。

【描述1.D.1】在web.xml中配置Servlet

    <servlet>
        <display-name>Hello</display-name>
        <!-- Servlet的引用名 -->
        <servlet-name>Hello</servlet-name>
        <!-- 所配置的Servlet類的完整類路徑 -->
        <servlet-class>com.haiersoft.ch01.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <!-- 前面配置的Servlet引用名-->
        <servlet-name>Hello</servlet-name>
        <!-- 訪問當(dāng)前Servlet的URL -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

在上述配置信息中,需要注意以下幾個方面:

■ Servlet別名,即<servlet-name>和</servlet-name>之間的命名可以隨意命名,但要遵循命名規(guī)范。

■ <servlet>和<servlet-mapping>元素可以配對出現(xiàn),通過Servlet別名進(jìn)行匹配。<servlet>元素也可以單獨出現(xiàn),通常用于初始化操作。

■ URL引用,即<url-pattern>和</url-pattern>之間的命名通常以“/”開頭。

啟動Tomcat,在IE中訪問http://localhost:8080/ch01/hello,運行結(jié)果如圖1-4所示。

圖1-4 運行結(jié)果

注意 關(guān)于Web應(yīng)用的開發(fā)過程及配置,可參考實踐1.G.2指導(dǎo)部分。

1.4 Servlet的生命周期

Servlet是運行在服務(wù)器上的,其生命周期由Servlet容器負(fù)責(zé)。Servlet生命周期是指Servlet實例從創(chuàng)建到響應(yīng)客戶請求直至銷毀的過程。Servlet API中定義了關(guān)于Servlet生命周期的3個方法。

init():用于Servlet初始化。當(dāng)容器創(chuàng)建Servlet實例后,會自動調(diào)用此方法。

service():用于服務(wù)處理。當(dāng)客戶端發(fā)出請求,容器會自動調(diào)用此方法進(jìn)行處理,并將處理結(jié)果響應(yīng)到客戶端。service()方法有兩個參數(shù),分別接收ServletRequest接口和ServletResponse接口的對象來處理請求和響應(yīng)。

destroy():用于銷毀Servlet。當(dāng)容器銷毀Servlet實例時自動調(diào)用此方法,釋放Servlet實例,清除當(dāng)前Servlet所持有的資源。

Servlet生命周期概括為以下幾個階段。

01 裝載Servlet:這項操作一般是動態(tài)執(zhí)行的,有些服務(wù)器提供了相應(yīng)的管理功能,可以在啟動的時候就裝載Servlet。

02 創(chuàng)建一個Servlet實例:容器創(chuàng)建Servlet的一個實例對象。

03 初始化:容器調(diào)用init()方法對Servlet實例進(jìn)行初始化。

04 服務(wù):當(dāng)容器接收到對此Servlet的請求時,將調(diào)用service()方法響應(yīng)客戶的請求。

05 銷毀:容器調(diào)用destroy()方法銷毀Servlet實例。

在Servlet生命周期的這幾個階段中,初始化init()方法僅執(zhí)行一次,是在服務(wù)器裝載Servlet時執(zhí)行的,以后無論有多少客戶訪問此Servlet,都不會重復(fù)執(zhí)行init()。即此Servlet在Servlet容器中只有單一實例;當(dāng)多個用戶訪問此Servlet時,會分為多個線程訪問此Servlet實例對象的service()方法。在service()方法內(nèi),容器會對客戶端的請求方式進(jìn)行判斷,如果是Get方式提交,則調(diào)用doGet()進(jìn)行處理;如果是Post方式提交,則調(diào)用doPost()進(jìn)行處理。圖1-5說明了Servlet生命周期的不同階段。

下面代碼演示了Servlet的生命周期。

圖1-5 Servlet的生命周期

【代碼1-1】ServletLife.java

    public class ServletLife extends HttpServlet {
        /**
        * 構(gòu)造方法
        */
        public ServletLife() {
            super();
        }
        /**
        * 初始化方法
        */
        public void init(ServletConfig config) throws ServletException {
            System.out.println("初始化時,init()方法被調(diào)用!");
        }
        protected void doGet(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            System.out.println("處理請求時,doGet()方法被調(diào)用。");
        }
        protected void doPost(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            System.out.println("處理請求時,doPost()方法被調(diào)用。");
        }
        /**
        * 用于釋放資源
        */
        public void destroy() {
            super.destroy();
            System.out.println("釋放系統(tǒng)資源時,destroy()方法被調(diào)用!");
        }
    }

啟動Tomcat,在IE中訪問http://localhost:8080/ch01/ServletLife,觀察控制臺輸出信息,如圖1-6所示。

圖1-6 Servlet生命周期

打開多個IE窗口,訪問此Servlet,觀察控制臺輸出,會發(fā)現(xiàn)init()方法只運行一次,而service()方法會對每次請求都做出響應(yīng)。

1.5 Servlet數(shù)據(jù)處理

Servlet數(shù)據(jù)處理主要包括讀取表單數(shù)據(jù)、HTTP請求報頭的處理和HTTP響應(yīng)報頭的設(shè)置。

1.5.1 讀取表單數(shù)據(jù)

當(dāng)訪問Internet網(wǎng)站時,在瀏覽器地址欄中會經(jīng)常看到如下所述的字符串:

    http://host/path?usr=tom&dest=ok

該字符串問號后面的部分為表單數(shù)據(jù)(Form Data)或查詢數(shù)據(jù)(Query Data),這些數(shù)據(jù)以“name=value”形式通過URL傳送,多個數(shù)據(jù)使用“&”分開,這種形式也稱為“查詢字符串”。查詢字符串緊跟在URL中的“?”后面,所有“名/值”對會被傳遞到服務(wù)器,這是服務(wù)器獲取客戶端信息所采用的最常見的方式。

表單數(shù)據(jù)可以通過GET請求方式提交給服務(wù)器,此種方式將數(shù)據(jù)跟在問號后附加到URL的結(jié)尾(查詢字符串形式);也可以采用POST請求方式提交給服務(wù)器,此種方式將在地址欄看不到表單數(shù)據(jù)信息,可用于大量數(shù)據(jù)的傳輸,并且比GET方式更安全。

在學(xué)習(xí)處理Form表單數(shù)據(jù)前,先來回顧《Web編程基礎(chǔ)》中學(xué)過的關(guān)于表單的基本知識。

(1)使用Form標(biāo)簽創(chuàng)建HTML表單。

使用action屬性指定對表單進(jìn)行處理的Servlet或JSP頁面的地址,可以使用絕對或相對URL。例如:

    <form action="...">...</form>

如果省略action屬性,那么數(shù)據(jù)將提交給當(dāng)前頁面對應(yīng)的URL。

(2)使用輸入元素收集用戶數(shù)據(jù)。

將這些元素放在Form標(biāo)簽內(nèi),并為每個輸入元素賦予一個name。文本字段是最常用的輸入元素,其創(chuàng)建方式如下:

    <input type="text" name="...">

(3)在接近表單的尾部放置提交按鈕。

例如:

    <input type="submit"/>

單擊提交按鈕時,瀏覽器會將數(shù)據(jù)提交給表單action對應(yīng)的服務(wù)器端程序。

1. Form表單數(shù)據(jù)

通過HttpServletRequest對象可以讀取Form標(biāo)簽中的表單數(shù)據(jù)。HttpServletRequest接口在javax.servlet.http包中定義,它擴(kuò)展了ServletRequest,并定義了描述一個HTTP請求的方法。當(dāng)客戶端請求Servlet時,一個HttpServletRequest類型的對象會被傳遞到Servlet的service()方法,進(jìn)而傳遞到doGet()或doPost()方法中去。此對象中封裝了客戶端的請求擴(kuò)展信息,包括HTTP方法(即GET或POST)、Cookie、身份驗證和表單數(shù)據(jù)等信息。

表1-1列出了HttpServletRequest接口中用于讀取表單數(shù)據(jù)的方法。

表1-1 HttpServletRequest接口中讀取表單數(shù)據(jù)的方法

默認(rèn)情況下,request.getParameter()使用服務(wù)器的當(dāng)前字符集解釋輸入。要改變這種默認(rèn)行為,需要使用setCharacterEncoding(String env)方法來設(shè)置字符集,例如:

    request.setCharacterEncoding("GBK");

下述內(nèi)容用于實現(xiàn)任務(wù)描述1.D.2,使用Servlet處理表單數(shù)據(jù),當(dāng)用戶提交的數(shù)據(jù)正確時(用戶名haier,密碼soft),輸出“登錄成功!”,否則提示“登錄失?。 薄?/p>

(1)首先編寫靜態(tài)頁面,用于接收用戶信息。

【描述1.D.2】index.html

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gbk">
    <title>登錄</title>
    <script language="javascript" type="">
            function LoginSubmit(){
                var user=document.Login.loginName.value;
                var pass=document.Login.password.value;
                if(user==null||user==""){
                    alert("請?zhí)顚懹脩裘?);
                }
                else if(pass==null||pass==""){
                    alert("請?zhí)顚懨艽a");
                }
                else document.Login.submit();
            }
    </script>
    </head>
    <body>
    <form method="POST" name="Login" action="LoginServlet">
      <p align="left">
      用戶名:<input type="text" name="loginName" size="20"></p>
      <p align="left">
      密&nbsp; 碼:<input type="password" name="password" size="20"></p>
      <p align="left">
      <input type="button" value="提交" name="B1" onclick="LoginSubmit()">
      <input type="reset" value="重置" name="B2"></p>
    </form>
    </body>
    </html>

上述HTML代碼中,使用JavaScript對用戶表單進(jìn)行初始驗證,驗證成功后才提交給LoginSevlet進(jìn)行處理。

(2)編寫Servlet處理用戶提交表單數(shù)據(jù)。

【描述1.D.2】LoginServlet.java

    public class LoginServlet extends HttpServlet {
        public LoginServlet() {
            super();
        }
    public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 設(shè)置請求的編碼字符為GBK(中文編碼)
            request.setCharacterEncoding("GBK");
            // 設(shè)置響應(yīng)的文本類型為html,編碼字符為GBK
            response.setContentType("text/html;charset=GBK");
            // 獲取輸出流
            PrintWriter out = response.getWriter();
            // 獲取表單數(shù)據(jù)
            String pass = request.getParameter("password");
            String user = request.getParameter("loginName");
            if ("haier".equals(user) && "soft".equals(pass)) {
                out.println("登錄成功!");
            } else {
                out.println("登錄失敗!");
            }
    }
    }

上述代碼中,在doGet()方法中調(diào)用了doPost()方法,這樣不管用戶以什么方式提交,處理過程都一樣。因為頁面中使用了中文,為了防止出現(xiàn)中文亂碼問題,所以需要設(shè)置請求和響應(yīng)的編碼字符集,使之能夠支持中文,如下所示:

    request.setCharacterEncoding("GBK");
    response.setContentType("text/html;charset=GBK");

獲取表單中的數(shù)據(jù)時,使用getParameter()方法通過參數(shù)名獲得參數(shù)值,例如:

    String pass = request.getParameter("password");

上面語句通過參數(shù)名“password”來獲取該參數(shù)的值。

注意 如果index.html中表單的提交方式為GET方式,則在瀏覽器地址欄中會出現(xiàn)查詢字符串形式的表單數(shù)據(jù)(如password=soft&user=haier),但在LoginServlet中獲取參數(shù)值的方式完全相同。

(3)在web.xml中注冊該Servlet。

【描述1.D.2】web.xml

    <servlet>
        <display-name>LoginServlet</display-name>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.haiersoft.ch01.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/LoginServlet</url-pattern>
    </servlet-mapping>

上述代碼中,注冊了一個名為“LoginServlet”的Servlet,當(dāng)請求的相對URL為“/LoginServlet”時,Servlet容器會將請求交給該Servlet進(jìn)行處理。

啟動Tomcat,在IE中訪問http://localhost:8080/ch01/index.html,運行結(jié)果如圖1-7所示。

圖1-7 index.html頁面

在“用戶名”文本欄中輸入“haier”,在“密碼”文本框中輸入“soft”。然后單擊“提交”按鈕,顯示結(jié)果如圖1-8所示。

當(dāng)輸入錯誤的用戶名或密碼時,則顯示“登錄失??!”,如圖1-9所示。

圖1-8 LoginServlet驗證成功

圖1-9 LoginServlet驗證失敗

Form表單數(shù)據(jù)中除了普通的表單項之外,在實際開發(fā)中會廣泛應(yīng)用到隱藏域。隱藏域是隱藏的HTML表單變量,可以用來存儲狀態(tài)信息,操作起來與一般的HTML輸入域(比如文本輸入域、復(fù)選框和單選按鈕)類似,同樣會被提交到服務(wù)器。隱藏域與普通的HTML輸入域之間的不同之處就在于客戶端不能看到或修改隱藏域的值。

隱藏域可以用來在客戶端和服務(wù)器之間透明地傳輸狀態(tài)信息,示例代碼如下。

【代 碼1-2】hidden.html

    <html>
    <head>
    <title>隱藏域</title>
    </head>
    <body bgcolor="blue">
    <form method="post" action="nameservlet">
    <p> 請輸入用戶名:<br>
    <input type="text" name="uname"><br>
    <input type="hidden" name="bcolor" value="blue"><br>
    <input type="submit" value="submit">
    </form>
    </body>
    </html>

上述代碼中使用隱藏域?qū)⒂脩羲矚g的背景色傳遞給服務(wù)器。在服務(wù)器端獲取隱藏域的數(shù)據(jù)與表單其他元素一樣,都是使用getParameter()方法通過參數(shù)名獲取其數(shù)據(jù)值。

2. 查詢字符串

查詢字符串是表單數(shù)據(jù)的另一種情況,它們實質(zhì)上是相同的。同樣,服務(wù)器端的Servlet也是通過HttpServletRequest對象的getParameter()方法或者getParameterValues()方法讀取URL中查詢字符串的信息,然后根據(jù)信息可以進(jìn)行查詢,再把查詢的結(jié)果返回。

下述代碼演示查詢字符串的應(yīng)用。

【代碼1-3】querystr.html

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=GBK">
    <title> 查詢字符串</title>
    </head>
    <body>
    <a href="TestURL?id=2010">下一頁</a>
    </body>
    </html>

上述代碼中,在超鏈接的URL中使用查詢字符串,在“?”后添加了“id=2010”,該語句傳遞了一個參數(shù)id,其值為2010。

【代碼1-4】TestURL

    public class TestURL extends HttpServlet {
        public TestURL() {
            super();
        }
        protected void doGet(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
        protected void doPost(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=GBK");
            PrintWriter out = response.getWriter();
            String id = request.getParameter("id");
            out.println("URL參數(shù)值是:" + id);
        }
    }

在上述代碼中,使用request對象的getParameter()方法獲取URL中的參數(shù)值,并輸出。

啟動Tomcat,在IE中訪問http://localhost:8080/ch01/querystr.html,顯示結(jié)果如圖1-10所示。

單擊“下一頁”超鏈接,顯示結(jié)果如圖1-11所示。

圖1-10 index.html

圖1-11 TestURL結(jié)果

1.5.2 處理HTTP請求報頭

客戶端瀏覽器向服務(wù)器發(fā)送請求的時候,除了用戶輸入的表單數(shù)據(jù)或者查詢數(shù)據(jù)之外,通常還會在GET/POST請求行后面加上一些附加的信息;而在服務(wù)器向客戶端的請求做出響應(yīng)的時候,也會自動向客戶端發(fā)送一些附加的信息。這些附加信息被稱為HTTP報頭,信息附加在請求信息后面稱為HTTP請求報頭,而附加在響應(yīng)信息后面則稱為HTTP響應(yīng)報頭。在Servlet中可以獲取或設(shè)置這些報頭的信息。

報頭信息的讀取比較簡單:只需將報頭的名稱作為參數(shù),調(diào)用HttpServletRequest的getHeader方法;如果當(dāng)前的請求中提供了對應(yīng)的報頭信息,則返回一個String,否則返回null。

另外,這些報頭的參數(shù)名稱不區(qū)分大小寫,也就是說,也可以通過getHeader("user-agent")來獲得User-Agent報頭。常用的HTTP請求報頭如表1-2所示。

表1-2 常用HTTP請求報頭

盡管getHeader()方法是讀取輸入報頭的通用方式,但由于幾種報頭的應(yīng)用很普遍,因此HttpServletRequest為它們提供了專門的訪問方法,如表1-3所示。

表1-3 HttpServletRequest獲取報頭信息的方法

下述代碼用于實現(xiàn)任務(wù)描述1.D.3,演示報頭信息的讀取方式。

【描述1.D.3】HttpHeadServlet.java

    public class HttpHeadServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
        protected void doPost(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=gbk");
            PrintWriter out = response.getWriter();
            StringBuffer buffer = new StringBuffer();
            buffer.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 "
                    + "Transitional//EN\">");
            buffer.append("<html>");
            buffer.append("<head><title>");
            String title = "請求表頭信息";
            buffer.append(title);
            buffer.append("</title></head>");
            buffer.append("<body>");
            buffer.append("<h1 align='center'>" + title + "</h1>");
            buffer.append("<b>Request Method: </b>");
            buffer.append(request.getMethod() + "<br/>");
            buffer.append("<b>Request URL: </b>");
            buffer.append(request.getRequestURI() + "<br/>");
            buffer.append("<b>Request Protocol: </b>");
            buffer.append(request.getProtocol() + "<br/>");
            buffer.append("<b>Request Local: </b>");
            buffer.append(request.getLocale() + "<br/><br/>");
            buffer.append("<table border='1' align='center'>");
            buffer.append("<tr bgcolor='#FFAD00'>");
            buffer.append("<th>Header Name</th><th>Header Value</th>");
            buffer.append("</tr>");
            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String headerName = (String) headerNames.nextElement();
                buffer.append("<tr>");
                buffer.append("<td>" + headerName + "</td>");
                buffer.append("<td>" + request.getHeader(headerName) + "</td>");
                buffer.append("</tr>");
            }
            buffer.append("</body>");
            buffer.append("</html>");
            out.println(buffer.toString());
        }
    }

上述代碼中,通過調(diào)用request對象中的getMethod()方法來獲取用戶請求方式;調(diào)用getRequestURI()方法來獲取用戶請求路徑;調(diào)用getHeaderNames()方法返回所有請求報頭名稱的集合,遍歷此集合并使用getHeader()提取報頭信息顯示。

啟動Tomcat,在IE中訪問http://localhost:8080/ch01/HttpHeadServlet,運行結(jié)果如圖1-12所示。

圖1-12 請求報頭信息

1.5.3 設(shè)置HTTP響應(yīng)報頭

在Servlet中,可以通過HttpServletResponse的setHeader()方法來設(shè)置HTTP響應(yīng)報頭,它接收兩個參數(shù),用于指定響應(yīng)報頭的名稱和對應(yīng)的值,語法格式如下:

    setHeader(String headerName,String headerValue)

常用的HTTP響應(yīng)報頭如表1-4所示。

表1-4 常用的HTTP響應(yīng)報頭

注意 一些舊版本的瀏覽器只支持HTTP 1.0的報頭,所以,為了保證程序具有良好的兼容性,應(yīng)該慎重地使用這些報頭,或者使用HttpServletRequest的getRequestProtocol()方法獲得HTTP的版本后再做選擇。

除了setHeader()方法外,還有兩個方法用于設(shè)置日期或者整型數(shù)據(jù)格式報頭:

    setDateHeader(String headerName, long ms)

    setIntHeader(String headerName, int headerValue)

此外,對于一些常用的報頭,在API中也提供了更方便的方法來設(shè)置它們,如表1-5所示。

表1-5 HttpServletResponse響應(yīng)方法

下述代碼用于實現(xiàn)任務(wù)描述1.D.4,通過設(shè)置響應(yīng)報頭,實現(xiàn)動態(tài)時鐘。

【描述1.D.4】DateServlet.java

    public class DateServlet extends HttpServlet {
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException { // 獲得一個向客戶發(fā)送數(shù)據(jù)的輸出流
            response.setContentType("text/html; charset=GBK");// 設(shè)置響應(yīng)的MIME類型
            PrintWriter out = response.getWriter();
            out.println("<html>");
            out.println("<body>");
            response.setHeader("Refresh", "1"); // 設(shè)置Refresh的值
            out.println("現(xiàn)在時間是:");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            out.println("<br/>" + sdf.format(new Date()));
            out.println("</body>");
            out.println("</html>");
        }
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    }

上述代碼中,通過設(shè)置響應(yīng)報頭,使得客戶端每隔一秒訪問一次當(dāng)前Servlet,從而在客戶端能夠動態(tài)地觀察時鐘的變化。實現(xiàn)每隔一秒動態(tài)刷新的功能代碼如下:

    response.setHeader("Refresh", "1");

其中,Refresh為響應(yīng)頭部信息;1是時間間隔值,以秒為單位。

啟動Tomcat,在IE中訪問http://localhost:8080/ch01/DateServlet,運行結(jié)果如圖1-13所示。

圖1-13 動態(tài)時鐘

注意 在任務(wù)描述1.D.4中,通過不斷地刷新當(dāng)前頁面來訪問DateServlet,從而實現(xiàn)了動態(tài)時鐘,在本書第8章通過AJAX技術(shù)可以實現(xiàn)無刷新時鐘,讀者可以通過觀察顯示效果對這兩種方式進(jìn)行比較。

1.6 重定向和請求轉(zhuǎn)發(fā)

重定向和請求轉(zhuǎn)發(fā)是Servlet處理完數(shù)據(jù)后進(jìn)行頁面跳轉(zhuǎn)的兩種主要方式。

1.6.1 重定向

重定向是指頁面重新定位到某個新地址,之前的Request失效,進(jìn)入一個新的Request,且跳轉(zhuǎn)后瀏覽器地址欄內(nèi)容將變?yōu)樾碌闹付ǖ刂贰V囟ㄏ蚴峭ㄟ^HttpServletResponse對象的sendRedirect()方法來實現(xiàn)的,該方法用于生成302響應(yīng)碼和Location響應(yīng)頭,從而通知客戶端去重新訪問Location響應(yīng)頭中指定的URL,其語法格式如下:

    pubilc void sendRedirect(java.lang.String location)throws java.io.IOException

其中:

■ location參數(shù)指定了重定向的URL,它可以是相對路徑也可以是絕對路徑。

使用sendRedirect()方法不僅可以重定向到當(dāng)前應(yīng)用程序中的其他資源,還可以重定向到其他應(yīng)用程序中的資源,例如:

    response.sendRedirect("/ch01/index.html");

上面語句重定向到當(dāng)前站點(ch01)的根目錄下的index.html界面。

下述代碼用于實現(xiàn)任務(wù)描述1.D.5,使用請求重定向方式使用戶自動訪問重定向后的頁面。

【描述1.D.5】RedirectServlet.java

    public class RedirectServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            response.setContentType("text/html; charset="GBK");
            PrintWriter out = response.getWriter();
            out.println("重定向前");
            response.sendRedirect(request.getContextPath() + "/myservlet");
            out.println("重定向后");
        }
    }

在web.xml配置文件中配置RedirectServlet的<url-pattern>為“/redirect”。

其中,myservlet對應(yīng)的Servlet代碼如下所示。

【描述1.D.5】MyServlet.java

    public class MyServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 設(shè)置響應(yīng)到客戶端的文本類型為HTML
            response.setContentType("text/html; charset=GBK");
            // 獲取輸出流
            PrintWriter out = response.getWriter();
            out.println("重定向和請求轉(zhuǎn)發(fā)");
        }
    }

在web.xml配置文件中配置MyServlet的<url-pattern>為“/myservlet”。

啟動Tomcat,在IE中訪問http://localhost:8080/ch01/redirect,顯示出了MyServlet輸出網(wǎng)頁中的內(nèi)容,這時瀏覽器地址欄中的地址變成了MyServlet的URL“http://localhost:8080/ch01/myservlet”,結(jié)果如圖1-14所示。

圖1-14 重定向地址欄變化

1.6.2 請求轉(zhuǎn)發(fā)

請求轉(zhuǎn)發(fā)是指將請求再轉(zhuǎn)發(fā)到另一頁面,此過程依然在Request范圍內(nèi),轉(zhuǎn)發(fā)后瀏覽器地址欄內(nèi)容不變。請求轉(zhuǎn)發(fā)使用RequestDispatcher接口中的forward()方法來實現(xiàn),該方法可以把請求轉(zhuǎn)發(fā)到另外一個資源,并讓該資源對瀏覽器的請求進(jìn)行響應(yīng)。

RequestDispatcher接口有以下兩個方法。

forward()方法:請求轉(zhuǎn)發(fā),可以從當(dāng)前Servlet跳轉(zhuǎn)到其他Servlet。

include()方法:引入其他Servlet。

RequestDispatcher是一個接口,通過使用HttpRequest對象的getRequestDispalcher()方法可以獲得該接口的實例對象,例如:

    RequestDispatcher rd = request.getRequestDispatcher(path);
    rd.forward(request,response);

下述代碼用于實現(xiàn)任務(wù)描述1.D.5,使用請求轉(zhuǎn)發(fā)方式使用戶自動訪問請求轉(zhuǎn)發(fā)后的頁面。

【描述1.D.5】ForwardServlet.java

    //請求轉(zhuǎn)發(fā)
    public class ForwardServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            response.setContentType("text/html; charset=GBK");
            PrintWriter out = response.getWriter();
            out.println("請求轉(zhuǎn)發(fā)前");
            RequestDispatcher rd = request.getRequestDispatcher("/myservlet");
            rd.forward(request, response);
            out.println("請求轉(zhuǎn)發(fā)后");
        }
    }

在IE中訪問http://localhost:8080/ch01/forward,瀏覽器中顯示出了MyServlet輸出網(wǎng)頁中的內(nèi)容,這時瀏覽器地址欄中的地址不會發(fā)生改變,結(jié)果如圖1-15所示。

圖1-15 請求轉(zhuǎn)發(fā)地址欄變化

通過上述ForwardServlet和RedirectServlet的運行結(jié)果可以看出,轉(zhuǎn)發(fā)和重定向兩種方式在調(diào)用后地址欄中的URL是不同的,前者的地址欄不變,后者地址欄中的URL變成目標(biāo)URL。

此外,轉(zhuǎn)發(fā)和重定向最主要的區(qū)別是:轉(zhuǎn)發(fā)前后共享同一個request對象,而重定向前后不在一個請求中。

為了驗證請求轉(zhuǎn)發(fā)和重定向的區(qū)別,在示例中會用到HttpServletRequest的存取和讀取屬性值的兩個方法。

getAttribute(String name):取得name的屬性值,如果屬性不存在則返回null。

setAttribute(String name,Object value):將value對象以name名稱綁定到request對象中。

注意 除HttpServletRequest接口外,HttpSession和ServletContext接口也擁有g(shù)etAttribute()和setAttribute()方法,分別用來讀取和設(shè)置這兩類對象中的屬性值。

下述內(nèi)容用于實現(xiàn)任務(wù)描述1.D.5,通過請求參數(shù)的傳遞來驗證forward()方法和sendRedirect()方法在request對象共享上的區(qū)別。

(1)改寫RedirectServlet,在sendRedirect()方法中加上查詢字符串。

【描述1.D.5】RedirectServlet.java

    public class RedirectServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            response.setContentType("text/html; charset=GBK");
            PrintWriter out = response.getWriter();
            request.setAttribute("test","helloworld");
            out.println("重定向前");
            response.sendRedirect(request.getContextPath() + "/myservlet ");
            out.println("重定向后");
        }
    }

上述代碼中,調(diào)用了setAttribute()方法把test屬性值helloworld存儲到request對象中。

(2)改寫MyServlet,獲取request對象中的test屬性值。

【描述1.D.5】MyServlet.java

    public class MyServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 設(shè)置響應(yīng)到客戶端的文本類型為HTML
            response.setContentType("text/html; charset=GBK");
            String test =(String)request.getAttribute("test");
            // 獲取輸出流
            PrintWriter out = response.getWriter();
            out.println("重定向和請求轉(zhuǎn)發(fā)");
            out.println(test);
        }
    }

上述代碼中,從request對象中獲取test屬性值。

啟動Tomcat,在IE中訪問http://localhost:8080/ch01/redirect,運行結(jié)果如下:

    重定向和請求轉(zhuǎn)發(fā)null

由此可知,在MyServlet中的request對象中并沒有獲得RedirectServlet中request對象設(shè)置的值。

(3)改寫ForwardServlet,獲取request對象中的test屬性值。

【描述1.D.5】ForwardServlet.java

    // 請求轉(zhuǎn)發(fā)
    public class ForwardServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            response.setContentType("text/html; charset=GBK");
            request.setAttribute("test","helloworld");
            PrintWriter out = response.getWriter();
            out.println("請求轉(zhuǎn)發(fā)前");
            RequestDispatcher rd = request.getRequestDispatcher("/myservlet");
            rd.forward(request, response);
            out.println("請求轉(zhuǎn)發(fā)后");
        }
    }

上述代碼中,從request對象中獲取test屬性值。

啟動Tomcat,在IE中訪問http://localhost:8080/ch01/forward,運行結(jié)果如下:

    重定向和請求轉(zhuǎn)發(fā)helloworld

由此可知,在MyServlet中的request對象中獲得了ForwardServlet的request對象設(shè)置的值。

通過對上述示例的運行結(jié)果進(jìn)行比較,forward()和sendRedirect()兩者的區(qū)別總結(jié)如下:

■ forward()只能將請求轉(zhuǎn)發(fā)給同一個Web應(yīng)用中的組件,而sendRedirect()方法不僅可以重定向到當(dāng)前應(yīng)用程序中的其他資源,還可以重定向到其他站點中的資源。如果傳給sendRedirect()方法的相對URL以“/”開頭,它是相對于整個Web站點的根目錄;如果創(chuàng)建RequestDispatcher對象時指定的相對URL以“/”開頭,它是相對于當(dāng)前Web應(yīng)用程序的根目錄。

■ sendRedirect()方法重定向的訪問過程結(jié)束后,瀏覽器地址欄中顯示的URL會發(fā)生改變,由初始的URL地址變成重定向的目標(biāo)URL;而調(diào)用forward()方法的請求轉(zhuǎn)發(fā)過程結(jié)束后,瀏覽器地址欄保持初始的URL地址不變。

■ forward()方法的調(diào)用者與被調(diào)用者之間共享相同的request對象和response對象,它們屬于同一個請求和響應(yīng)過程;而sendRedirect()方法調(diào)用者和被調(diào)用者使用各自的request對象和response對象,它們屬于兩個獨立的請求和響應(yīng)過程。

1.7 小結(jié)

通過本章的學(xué)習(xí),學(xué)生應(yīng)該能夠?qū)W會:

■ 動態(tài)網(wǎng)站開發(fā)技術(shù)有Servlet、JSP、PHP、ASP、ASP.NET和CGI等。

■ Servlet是運行在服務(wù)器端的Java程序,內(nèi)嵌HTML。

■ Servlet生命周期的三個方法分別是init()、service()和destroy()。

■ Servlet處理GET和POST請求時分別使用doGet()和doPost()方法進(jìn)行處理。

■ HttpServletRequest的getParameter(“參數(shù)名稱”)獲取表單、URL參數(shù)值。

■ HttpServletResponse的getWriter()獲取向客戶端發(fā)送信息的輸出流。

■ HttpServletRequest的getHeader(“報頭名稱”)獲取相關(guān)報頭信息。

■ 請求轉(zhuǎn)發(fā)和重定向都可以使瀏覽器獲得另外一個URL所指向的資源。

■ 請求轉(zhuǎn)發(fā)通常由RequestDispatcher接口的forward()方法實現(xiàn),轉(zhuǎn)發(fā)前后共享同一個請求對象。

■ 重定向由HttpServletResponse接口的sendRedirect()方法實現(xiàn),重定向不共享同一個請求對象。

練習(xí)

1. 下列選項中屬于動態(tài)網(wǎng)站技術(shù)的是______。(多選)

A. PHP

B. ASP

C. JavaScript

D. JSP

2. 下列關(guān)于Servlet的說法正確的是______。(多選)

A. Servlet是一種動態(tài)網(wǎng)站技術(shù)

B. Servlet運行在服務(wù)器端

C. Servlet針對每個請求使用1個進(jìn)程來處理

D. Servlet與普通的Java類一樣,可以直接運行,不需要環(huán)境支持

3. 下列關(guān)于Servlet的編寫方式正確的是______。(多選)

A. 必須是HttpServlet的子類

B. 通常需要覆蓋doGet()和doPost()方法或其中之一

C. 通常需要覆蓋service()方法

D. 通常需要在web.xml文件中聲明<servlet>和<servlet-mapping>兩個元素

4. 下列關(guān)于Servlet生命周期的說法正確的是______。(多選)

A. 構(gòu)造方法只會調(diào)用一次,在容器啟動時調(diào)用

B. init()方法只會調(diào)用一次,在第一次請求此Servlet時調(diào)用

C. service()方法在每次請求此Servlet時都會被調(diào)用

D. destroy()方法在每次請求完畢時會被調(diào)用

5. 下列方式中可以執(zhí)行TestServlet(路徑為 /test)的doPost()方法的是______。(多選)

A. 在IE中直接訪問http://localhost:8080/網(wǎng)站名/test

B. <form action="/網(wǎng)站名/test"> 提交此表單

C. <form action="/網(wǎng)站名/test" method="post"> 提交此表單

D. <form id="form1">,在JavaScript中執(zhí)行下述代碼:

    document.getElementById("form1").action="/網(wǎng)站名/test";
    document.getElementById("form1").method="post";
    document.getElementById("form1").submit();

6. 針對下述JSP頁面,在Servlet中需要得到用戶選擇的愛好的數(shù)量,最合適的代碼是______。

    <input type="checkbox" name="aihao" value="1"/>游戲<br/>
    <input type="checkbox" name="aihao" value="2"/>運動<br/>
    <input type="checkbox" name="aihao" value="3"/>棋牌<br/>
    <input type="checkbox" name="aihao" value="4"/>美食<br/>

A. request.getParameter("aihao").length

B. request.getParameter("aihao").size()

C. request.getParameterValues("aihao").length

D. request.getParameterValues("aihao").size()

7. 用戶使用POST方式提交的數(shù)據(jù)中存在漢字(使用GBK字符集),在Servlet中需要使用下述______語句處理。

A. request.setCharacterEncoding("GBK");

B. request.setContentType("text/html;charset=GBK");

C. response.setCharacterEncoding("GBK");

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

8. 簡述Servlet的生命周期。Servlet在第一次和第二次被訪問時,其生命周期方法的執(zhí)行有何區(qū)別?

9. 簡述轉(zhuǎn)發(fā)和重定向兩種頁面跳轉(zhuǎn)方式的區(qū)別,在Servlet中分別使用什么方法實現(xiàn)?

主站蜘蛛池模板: 宾川县| 平度市| 宁津县| 随州市| 南平市| 松滋市| 汝南县| 阳谷县| 永寿县| 锦屏县| 黔南| 阳信县| 招远市| 高青县| 杭锦旗| 怀宁县| 武安市| 科技| 寿阳县| 青海省| 满洲里市| 香格里拉县| 新营市| 张家口市| 勐海县| 黄梅县| 香港| 乌兰浩特市| 新巴尔虎左旗| 富阳市| 横山县| 阜阳市| 和顺县| 凤冈县| 定日县| 图木舒克市| 宁明县| 将乐县| 遵义市| 鹿邑县| 江安县|