处理表单

Java Servlet的好处之一就在于所有上述解析操作都能够自动完成。只需要简单地调用一下HttpServletRequest的getParameter方法、在调用参数中提供表单变量的名字（大小写敏感）即可，而且GET请求和POST请求的处理方法完全相同。

getParameter方法的返回值是一个字符串，它是参数中指定的变量名字第一次出现所对应的值经反编码得到得字符串（可以直接使用）。如果指定的表单变量存在，但没有值，getParameter返回空字符串；如果指定的表单变量不存在，则返回null。如果表单变量可能对应多个值，可以用getParameterValues来取代getParameter。getParameterValues能够返回一个字符串数组。

最后，虽然在实际应用中Servlet很可能只会用到那些已知名字的表单变量，但在调试环境中，获得完整的表单变量名字列表往往是很有用的，利用getParamerterNames方法可以方便地实现这一点。getParamerterNames返回的是一个Enumeration，其中的每一项都可以转换为调用getParameter的字符串。

## 实例：读取三个表单变量

下面是一个简单的例子，它读取三个表单变量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来读取这些数据。

1. ThreeParams.java

2. package hall;

3.

4. import java.io.*;

5. import javax.servlet.*;

6. import javax.servlet.http.*;

7. import java.util.*;

8. public class ThreeParams extends HttpServlet {

9. public void doGet(HttpServletRequest request,

10. HttpServletResponse response)

11. throws ServletException, IOException {

12. response.setContentType("text/html");

13. PrintWriter out = response.getWriter();

14. String title = "读取三个请求参数";

15. out.println(ServletUtilities.headWithTitle(title) +

16. "＜BODY＞＼n" +

17. "＜H1 ALIGN=CENTER＞" + title + "＜/H1＞＼n" +

18. "＜UL＞＼n" +

19. " ＜LI＞param1: "

20. + request.getParameter("param1") + "＼n" +

21. " ＜LI＞param2: "

22. + request.getParameter("param2") + "＼n" +

23. " ＜LI＞param3: "

24. + request.getParameter("param3") + "＼n" +

25. "＜/UL＞＼n" +

26. "＜/BODY＞＜/HTML＞");

27. }

28.

29. public void doPost(HttpServletRequest request,

30. HttpServletResponse response)

31. throws ServletException, IOException {

32. doGet(request, response);

33. }

34. }

## 实例：输出所有的表单数据

下面这个例子寻找表单所发送的所有变量名字，并把它们放入表格中，没有值或者有多个值的变量都突出显示。

首先，程序通过HttpServletRequest的getParameterNames方法得到所有的变量名字，getParameterNames返回的是一个Enumeration。接下来，程序用循环遍历这个Enumeration，通过hasMoreElements确定何时结束循环，利用nextElement得到Enumeration中的各个项。由于nextElement返回的是一个Object，程序把它转换成字符串后再用这个字符串来调用getParameterValues。

getParameterValues返回一个字符串数组，如果这个数组只有一个元素且等于空字符串，说明这个表单变量没有值，Servlet以斜体形式输出“No Value”；如果数组元素个数大于1，说明这个表单变量有多个值，Servlet以HTML列表形式输出这些值；其他情况下Servlet直接把变量值放入表格。

ShowParameters.java

注意，ShowParameters.java用到了前面介绍过的ServletUtilities.java。

1. package hall;

2.

3. import java.io.*;

4. import javax.servlet.*;

5. import javax.servlet.http.*;

6. import java.util.*;

7.

8. public class ShowParameters extends HttpServlet {

9. public void doGet(HttpServletRequest request,

10. HttpServletResponse response)

11. throws ServletException, IOException {

12. response.setContentType("text/html");

13. PrintWriter out = response.getWriter();

14. String title = "读取所有请求参数";

15. out.println(ServletUtilities.headWithTitle(title) +

16. "＜BODY BGCOLOR=＼"#FDF5E6＼"＞＼n" +

17. "＜H1 ALIGN=CENTER＞" + title + "＜/H1＞＼n" +

18. "＜TABLE BORDER=1 ALIGN=CENTER＞＼n" +

19. "＜TR BGCOLOR=＼"#FFAD00＼"＞＼n" +

20. "＜TH＞参数名字＜TH＞参数值");

21. Enumeration paramNames = request.getParameterNames();

22. while(paramNames.hasMoreElements()) {

23. String paramName = (String)paramNames.nextElement();

24. out.println("＜TR＞＜TD＞" + paramName + "＼n＜TD＞");

25. String[] paramValues = request.getParameterValues(paramName);

26. if (paramValues.length == 1) {

27. String paramValue = paramValues[0];

28. if (paramValue.length() == 0)

29. out.print("＜I＞No Value＜/I＞");

30. else

31. out.print(paramValue);

32. } else {

33. out.println("＜UL＞");

34. for(int i=0; i＜paramValues.length; i++) {

35. out.println("＜LI＞" + paramValues[i]);

36. }

37. out.println("＜/UL＞");

38. }

39. }

40. out.println("＜/TABLE＞＼n＜/BODY＞＜/HTML＞");

41. }

42.

43. public void doPost(HttpServletRequest request,

44. HttpServletResponse response)

45. throws ServletException, IOException {

46. doGet(request, response);

47. }

48. }

49.

## 测试表单

下面是向上述Servlet发送数据的表单PostForm.html。就像所有包含密码输入域的表单一样，该表单用POST方法发送数据。我们可以看到，在Servlet中同时实现doGet和doPost这两种方法为表单制作带来了方便。

1. ＜!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"＞

2. ＜HTML＞

3. ＜HEAD＞

4. ＜TITLE＞示例表单＜/TITLE＞

5. ＜/HEAD＞

6.

7. ＜BODY BGCOLOR="#FDF5E6"＞

8. ＜H1 ALIGN="CENTER"＞用POST方法发送数据的表单＜/H1＞

9.

10. ＜FORM ACTION="/servlet/hall.ShowParameters"

11. METHOD="POST"＞

12. Item Number:

13. ＜INPUT TYPE="TEXT" NAME="itemNum"＞＜BR＞

14. Quantity:

15. ＜INPUT TYPE="TEXT" NAME="quantity"＞＜BR＞

16. Price Each:

17. ＜INPUT TYPE="TEXT" NAME="price" VALUE="[GV_contentText]quot;＞＜BR＞

18. ＜HR＞

19. First Name:

20. ＜INPUT TYPE="TEXT" NAME="firstName"＞＜BR＞

21. Last Name:

22. ＜INPUT TYPE="TEXT" NAME="lastName"＞＜BR＞

23. Middle Initial:

24. ＜INPUT TYPE="TEXT" NAME="initial"＞＜BR＞

25. Shipping Address:

26. ＜TEXTAREA NAME="address" ROWS=3 COLS=40＞＜/TEXTAREA＞＜BR＞

27. Credit Card:＜BR＞

28. ＜INPUT TYPE="RADIO" NAME="cardType"

29. VALUE="Visa"＞Visa＜BR＞

30. ＜INPUT TYPE="RADIO" NAME="cardType"

31. VALUE="Master Card"＞Master Card＜BR＞

32. ＜INPUT TYPE="RADIO" NAME="cardType"

33. VALUE="Amex"＞American Express＜BR＞

34. ＜INPUT TYPE="RADIO" NAME="cardType"

35. VALUE="Discover"＞Discover＜BR＞

36. ＜INPUT TYPE="RADIO" NAME="cardType"

37. VALUE="Java SmartCard"＞Java SmartCard＜BR＞

38. Credit Card Number:

39. ＜INPUT TYPE="PASSWORD" NAME="cardNum"＞＜BR＞

40. Repeat Credit Card Number:

41. ＜INPUT TYPE="PASSWORD" NAME="cardNum"＞＜BR＞＜BR＞

42. ＜CENTER＞

43. ＜INPUT TYPE="SUBMIT" VALUE="Submit Order"＞

44. ＜/CENTER＞

45. ＜/FORM＞

46.

47. ＜/BODY＞

48. ＜/HTML＞