Sun 认证 Web 组件开发人员/第 1 部分/HTTP 请求
HttpServletRequest 可能是整个 JEE 框架中最重要的接口。它是用户与服务器通信的方式。每次用户需要从服务器获取东西时,他都会发送一个请求,该请求在 Web 容器内被转换为 HttpServletRequest 对象。
首先要注意的是 HttpServletRequest 扩展了另一个接口,即 ServletRequest 接口。这是因为 Web 容器并非设计为仅处理 HTTP 请求和响应,而是处理各种请求,使用多种协议。尽管如此,如前所述,HTTP 是最常用的协议,并且您可能在 100% 的时间内只会看到 HTTPRequests 输入和 HTTPResponses 输出。这就是 JEE API 有一个名为 javax.servlet.http
的特定包的原因,其中包含针对 HTTP 协议的所有特定类和接口。
HttpServletRequest 中有许多方法非常方便用于操作用户的请求。您可以从 Web 容器为您创建的对象中获取各种信息。一些示例包括
- HTTP 头部
- Cookie
- 查询字符串
- 用户的 IP 和端口
- 表单参数
- 等等。
HttpServletRequest 对象最常见的用途是获取用户在 HTML 表单中发送的参数。参数是服务器从客户端接收的用于特定任务的字符串,例如:处理查询或保存或更新数据库记录。
参数通过两种方式发送:在 HTML 表单中和在查询字符串中。在这两种方式中,参数都是由键标识的值。同一个键可以有多个值,这意味着同一个参数可以发送两次,具有两个不同的值。一些有效的参数示例是
- name=John
- fname=John&lname=Doe&[email protected]
- query=java&lang=en
- name=John&name=Mary&name=Josh
使用 POST 方法通过 HTML 表单发送时,数据会发送在请求主体中,并且可以是任何大小。使用 GET 时,数据受 URL 最大大小的限制,这取决于浏览器或服务器,因此不建议使用 GET 发送大量数据。
下面您可以看到关于 HTML 表单和查询字符串的更详细的解释。
HTML 表单是用户向服务器发送数据的几种方式之一。如前所述,HTML 表单可以通过两种不同的方式发送数据:POST 和 GET。如果要发送更新服务器内容的数据,建议使用 POST,有时因为数据量可能很大,有时因为可能存在不会在 URL 中加密的机密数据。
要使用 HTML 表单向服务器发送参数,只需命名并使用您想要的名称识别表单子元素,然后在服务器中按名称获取它。一个非常简单的例子是用户发送以下表单
<form method="POST" action="someUrl.do">
What is your name?<br />
<input type="text" id="name" name="name" /><input type="submit" />
</form>
这将呈现类似于这样的内容
然后,servlet 可以接收带有参数的 HttpServletRequest 并打印一个hello消息
package org.wikibooks.scwcd;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
public void doPost (HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
String name = request.getParameter("name");
if (name != null) {
PrintWriter out = response.getWriter();
out.println("Hello " + name + "!");
out.flush();
}
}
}
这将导致一个页面显示消息“Hello [用户名]!”。
要查看服务器收到的所有参数,可以使用以下 Servlet
package org.wikibooks.scwcd;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class EchoParameters extends HttpServlet {
public void doPost (HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
PrintWriter out = response.getWriter();
out.println("<html><body>All parameters:<ul>");
Enumeration params = request.getParameterNames();
String name;
while (params.hasMoreElements()) {
name = (String)params.nextElement();
out.println("<li>Key : " + name + "<br />Values: <ul>");
for (String value : request.getParameterValues(name)) {
out.println("<li>" + value + "</li>");
}
out.println("</ul>");
}
out.println("</ul></body></html>");
out.flush();
}
}
查询字符串是一个格式特定的字符串,附加在 URL 的末尾。该字符串可以在问号符号 (?
) 后附加,包含由与符号 (&
) 分隔的键/值对。一个简单的例子是 http://www.google.com/search?q=java
,其中查询字符串是 q=java
。这样,服务器会收到一个值为“java”的参数“q”,这意味着该 URL 是 google.com
域 (服务器) 内的 search
资源的query。
要将值发送到查询字符串中,只需在 HTML 表单中使用 GET
方法,如上所述。
浏览器会自动对 URL 进行编码,以便服务器能够正确地解释它,因为有一些特殊的符号不能直接发送,例如 @
。其中一些符号用于特殊目的,不得在查询字符串中的键或值中使用,因此必须对其进行编码,否则服务器将误解 URL,查询字符串可能会损坏。[2] [3]。
查询字符串对于保存应用程序状态很有用:用户所在的位置或他们执行的某些操作,可以将其添加书签以供以后访问。但要记住的是,由于它们可以保存,因此查询字符串中不应包含机密数据,例如信用卡号码。
HTTP 头部是客户端(大多数情况下是浏览器)和服务器用于检查彼此想要什么以及他们期望如何接收答案的协议特定命令。访问标头的最简单方法是使用 HttpServletRequest.getHeader(String)
方法。它将返回一个表示服务器为特定头部接收到的标头的值的 String
。
以下示例显示了 servlet 如何将从客户端接收的所有标头以 HTML 格式发送回去
package org.wikibooks.scwcd;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HttpHeadersExample extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Enumeration names = request.getHeaderNames();
String value = null, name = null;
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<p>All HTTP Headers:<ul>");
while (names.hasMoreElements()) {
name = (String) names.nextElement();
value = request.getHeader(name);
out.println("<li><strong>" + name + "</strong>: " + value + "</li>");
}
out.println("</ul></p></body></html>");
out.flush();
}
}
这将导致以下 HTML 代码,用于特定浏览器
<html><body>
<p>All HTTP Headers:<ul>
<li><strong>host</strong>: localhost:8080</li>
<li><strong>user-agent</strong>: Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3</li>
<li><strong>accept</strong>: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</li>
<li><strong>accept-language</strong>: en-us</li>
<li><strong>accept-encoding</strong>: gzip,deflate</li>
<li><strong>accept-charset</strong>: ISO-8859-1,utf-8;q=0.7,*;q=0.7</li>
<li><strong>keep-alive</strong>: 300</li>
<li><strong>connection</strong>: keep-alive</li>
</ul></p></body></html>
[1] - Java 企业版 API - 应用程序编程接口
[2] - URL 编码
[3] - HTML URL - 编码参考
[4]