jsp Servlet基礎入門學習:處理表單資料
最後更新:2017-02-28
來源:互聯網
上載者:User
js|servlet|資料
4.1 表單資料概述
如果你曾經使用過Web搜尋引擎,或者瀏覽過線上書店、股票價格、機票資訊,或許會留意到一些古怪的URL,比如“http://host/path?user=Marty+Hall&origin=bwi&dest=lax”。這個URL中位於問號後面的部分,即“user=Marty+Hall&origin=bwi&dest=lax”,就是表單資料,這是將Web頁面資料發送給伺服器程式的最常用方法。對於GET請求,表單資料附加到URL的問號後面(如上例所示);對於POST請求,表單資料用一個單獨的行發送給伺服器。
以前,從這種形式的資料提取出所需要的表單變數是CGI編程中最麻煩的事情之一。首先,GET請求和POST請求的資料提取方法不同:對於GET請求,通常要通過QUERY_STRING環境變數提取資料;對於POST請求,則一般通過標準輸入提取資料。第二,程式員必須負責在“&”符號處截斷變數名字-變數值對,再分離出變數名字(等號左邊)和變數值(等號右邊)。第三,必須對變數值進行URL反編碼操作。因為發送資料的時候,字母和數字以原來的形式發送,但空格被轉換成加號,其他字元被轉換成“%XX”形式,其中XX是十六進位表示的字元ASCII(或者ISO Latin-1)編碼值。例如,如果HTML表單中名為“users”的域值為“~hall, ~gates, and ~mcnealy”,則實際向伺服器發送的資料為“users=%7Ehall%2C+%7Egates%2C+and+%7Emcnealy”。最後,即第四個導致解析表單資料非常困難的原因在於,變數值既可能被省略(如“param1=val1&param2=&param3=val3”),也有可能一個變數擁有一個以上的值,即同一個變數可能出現一次以上(如“param1=val1&param2=val2&param1=val3”)。
Java Servlet的好處之一就在於所有上述解析操作都能夠自動完成。只需要簡單地調用一下HttpServletRequest的getParameter方法、在調用參數中提供表單變數的名字(大小寫敏感)即可,而且GET請求和POST請求的處理方法完全相同。
getParameter方法的傳回值是一個字串,它是參數中指定的變數名字第一次出現所對應的值經反編碼得到得字串(可以直接使用)。如果指定的表單變數存在,但沒有值,getParameter返回Null 字元串;如果指定的表單變數不存在,則返回null。如果表單變數可能對應多個值,可以用getParameterValues來取代getParameter。getParameterValues能夠返回一個字串數組。
最後,雖然在實際應用中Servlet很可能只會用到那些已知名字的表單變數,但在調試環境中,獲得完整的表單變數名字列表往往是很有用的,利用getParamerterNames方法可以方便地實現這一點。getParamerterNames返回的是一個Enumeration,其中的每一項都可以轉換為調用getParameter的字串。
4.2 執行個體:讀取三個表單變數
下面是一個簡單的例子,它讀取三個表單變數param1、param2和param3,並以HTML列表的形式列出它們的值。請注意,雖然在發送應答內容之前必須指定應答類型(包括內容類型、狀態以及其他HTTP頭資訊),但Servlet對何時讀取請求內容卻沒有什麼要求。
另外,我們也可以很容易地把Servlet做成既能處理GET請求,也能夠處理POST請求,這隻需要在doPost方法中調用doGet方法,或者覆蓋service方法(service方法調用doGet、doPost、doHead等方法)。在實際編程中這是一種標準的方法,因為它只需要很少的額外工作,卻能夠增加用戶端編碼的靈活性。
如果你習慣用傳統的CGI方法,通過標準輸入讀取POST資料,那麼在Servlet中也有類似的方法,即在HttpServletRequest上調用getReader或者getInputStream,但這種方法對普通的表單變數來說太麻煩。然而,如果是要上傳檔案,或者POST資料是通過專門的客戶程式而不是HTML表單發送,那麼就要用到這種方法。
注意用第二種方法讀取POST資料時,不能再用getParameter來讀取這些資料。
ThreeParams.java
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
public class ThreeParams extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "讀取三個請求參數";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY>\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<UL>\n" +
" <LI>param1: "
+ request.getParameter("param1") + "\n" +
" <LI>param2: "
+ request.getParameter("param2") + "\n" +
" <LI>param3: "
+ request.getParameter("param3") + "\n" +
"</UL>\n" +
"</BODY></HTML>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
4.3 執行個體:輸出所有的表單資料
下面這個例子尋找表單所發送的所有變數名字,並把它們放入表格中,沒有值或者有多個值的變數都反白。
首先,程式通過HttpServletRequest的getParameterNames方法得到所有的變數名字,getParameterNames返回的是一個Enumeration。接下來,程式用迴圈遍曆這個Enumeration,通過hasMoreElements確定何時結束迴圈,利用nextElement得到Enumeration中的各個項。由於nextElement返回的是一個Object,程式把它轉換成字串後再用這個字串來調用getParameterValues。
getParameterValues返回一個字串數組,如果這個數組只有一個元素且等於Null 字元串,說明這個表單變數沒有值,Servlet以斜體形式輸出“No Value”;如果數組元素個數大於1,說明這個表單變數有多個值,Servlet以HTML列表形式輸出這些值;其他情況下Servlet直接把變數值放入表格。
ShowParameters.java
注意,ShowParameters.java用到了前面介紹過的ServletUtilities.java。
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
public class ShowParameters extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "讀取所有請求參數";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<TABLE BORDER=1 ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
"<TH>參數名字<TH>參數值");
Enumeration paramNames = request.getParameterNames();
while(paramNames.hasMoreElements()) {
String paramName = (String)paramNames.nextElement();
out.println("<TR><TD>" + paramName + "\n<TD>");
String[] paramValues = request.getParameterValues(paramName);
if (paramValues.length == 1) {
String paramValue = paramValues[0];
if (paramValue.length() == 0)
out.print("<I>No Value</I>");
else
out.print(paramValue);
} else {
out.println("<UL>");
for(int i=0; i<paramValues.length; i++) {
out.println("<LI>" + paramValues[i]);
}
out.println("</UL>");
}
}
out.println("</TABLE>\n</BODY></HTML>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
測試表單
下面是向上述Servlet發送資料的表單PostForm.html。就像所有包含密碼輸入欄位的表單一樣,該表單用POST方法發送資料。我們可以看到,在Servlet中同時實現doGet和doPost這兩種方法為表單製作帶來了方便。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>樣本表單</TITLE>
</HEAD>
<BODY BGCOLOR="#FDF5E6">
<H1 ALIGN="CENTER">用POST方法發送資料的表單</H1>
<FORM ACTION="/servlet/hall.ShowParameters"
METHOD="POST">
Item Number:
<INPUT TYPE="TEXT" NAME="itemNum"><BR>
Quantity:
<INPUT TYPE="TEXT" NAME="quantity"><BR>
Price Each:
<INPUT TYPE="TEXT" NAME="price" VALUE="[GV_contentText]quot;><BR>
<HR>
First Name:
<INPUT TYPE="TEXT" NAME="firstName"><BR>
Last Name:
<INPUT TYPE="TEXT" NAME="lastName"><BR>
Middle Initial:
<INPUT TYPE="TEXT" NAME="initial"><BR>
Shipping Address:
<TEXTAREA NAME="address" ROWS=3 COLS=40></TEXTAREA><BR>
Credit Card:<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Visa">Visa<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Master Card">Master Card<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Amex">American Express<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Discover">Discover<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Java SmartCard">Java SmartCard<BR>
Credit Card Number:
<INPUT TYPE="PASSWORD" NAME="cardNum"><BR>
Repeat Credit Card Number:
<INPUT TYPE="PASSWORD" NAME="cardNum"><BR><BR>
<CENTER>
<INPUT TYPE="SUBMIT" VALUE="Submit Order">
</CENTER>
</FORM>
</BODY>
</HTML>