一表单数据概述
如果你曾经使用过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)编码值例如如果HTML表单中名为“users”的域值为“~hall ~gates and ~mcnealy”则实际向服务器发送的数据为“users=%Ehall%C+%Egates%C+and+%Emcnealy”最后即第四个导致解析表单数据非常困难的原因在于变量值既可能被省略(如“param=val&param=&param=val”)也有可能一个变量拥有一个以上的值即同一个变量可能出现一次以上(如“param=val&param=val&param=val”)
Java Servlet的好处之一就在于所有上述解析操作都能够自动完成只需要简单地调用一下HttpServletRequest的getParameter方法在调用参数中提供表单变量的名字(大小写敏感)即可而且GET请求和POST请求的处理方法完全相同
getParameter方法的返回值是一个字符串它是参数中指定的变量名字第一次出现所对应的值经反编码得到得字符串(可以直接使用)如果指定的表单变量存在但没有值getParameter返回空字符串如果指定的表单变量不存在则返回null如果表单变量可能对应多个值可以用getParameterValues来取代getParametergetParameterValues能够返回一个字符串数组
最后虽然在实际应用中Servlet很可能只会用到那些已知名字的表单变量但在调试环境中获得完整的表单变量名字列表往往是很有用的利用getParamerterNames方法可以方便地实现这一点getParamerterNames返回的是一个Enumeration其中的每一项都可以转换为调用getParameter的字符串
二 实例读取三个表单变量
下面是一个简单的例子它读取三个表单变量paramparam和param并以HTML列表的形式列出它们的值请注意虽然在发送应答内容之前必须指定应答类型(包括内容类型状态以及其他HTTP头信息)但Servlet对何时读取请求内容却没有什么要求
另外我们也可以很容易地把Servlet做成既能处理GET请求也能够处理POST请求这只需要在doPost方法中调用doGet方法或者覆盖service方法(service方法调用doGetdoPostdoHead等方法)在实际编程中这是一种标准的方法因为它只需要很少的额外工作却能够增加客户端编码的灵活性
如果你习惯用传统的CGI方法通过标准输入读取POST数据那么在Servlet中也有类似的方法即在HttpServletRequest上调用getReader或者getInputStream但这种方法对普通的表单变量来说太麻烦然而如果是要上载文件或者POST数据是通过专门的客户程序而不是HTML表单发送那么就要用到这种方法
注意用第二种方法读取POST数据时不能再用getParameter来读取这些数据
ThreeParams
java
package hall;
import java
io
*;
import javax
servlet
*;
import javax
servlet
*;
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" +
"<H
ALIGN=CENTER>" + title + "</H
>\n" +
"<UL>\n" +
" <LI>param
: "
+ request
getParameter("param
") + "\n" +
" <LI>param
: "
+ request
getParameter("param
") + "\n" +
" <LI>param
: "
+ request
getParameter("param
") + "\n" +
"</UL>\n" +
"</BODY></HTML>");
}
public void doPost(HttpServletRequest request
HttpServletResponse response)
throws ServletException
IOException {
doGet(request
response);
}
}
实例输出所有的表单数据
下面这个例子寻找表单所发送的所有变量名字并把它们放入表格中没有值或者有多个值的变量都突出显示
首先程序通过HttpServletRequest的getParameterNames方法得到所有的变量名字getParameterNames返回的是一个Enumeration接下来程序用循环遍历这个Enumeration通过hasMoreElements确定何时结束循环利用nextElement得到Enumeration中的各个项由于nextElement返回的是一个Object程序把它转换成字符串后再用这个字符串来调用getParameterValues
getParameterValues返回一个字符串数组如果这个数组只有一个元素且等于空字符串说明这个表单变量没有值Servlet以斜体形式输出“No Value”如果数组元素个数大于说明这个表单变量有多个值Servlet以HTML列表形式输出这些值其他情况下Servlet直接把变量值放入表格
ShowParametersjava
注意ShowParametersjava用到了前面介绍过的ServletUtilitiesjava
package hall;
import java
io
*;
import javax
servlet
*;
import javax
servlet
*;
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=\"#FDF
E
\">\n" +
"<H
ALIGN=CENTER>" + title + "</H
>\n" +
"<TABLE BORDER=
ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD
\">\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 ==
) {
String paramValue = paramValues[
];
if (paramValue
length() ==
)
out
print("<I>No Value</I>");
else
out
print(paramValue);
} else {
out
println("<UL>");
for(int i=
; 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发送数据的表单PostFormhtml就像所有包含密码输入域的表单一样该表单用POST方法发送数据我们可以看到在Servlet中同时实现doGet和doPost这两种方法为表单制作带来了方便
<!DOCTYPE HTML PUBLIC "
//W
C//DTD HTML
Transitional//EN">
<HTML>
<HEAD>
<TITLE>示例表单</TITLE>
</HEAD>
<BODY BGCOLOR="#FDF
E
">
<H
ALIGN="CENTER">用POST方法发送数据的表单</H
>
<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=
COLS=
></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>