Java Servlet 中的 doGet 和 doPost
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2349633/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
doGet and doPost in Servlets
提问by dedalo
I've developed an HTML page that sends information to a Servlet. In the Servlet, I am using the methods doGet()
and doPost()
:
我开发了一个将信息发送到 Servlet 的 HTML 页面。在 Servlet 中,我使用的方法doGet()
和doPost()
:
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String id = req.getParameter("realname");
String password = req.getParameter("mypassword");
}
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String id = req.getParameter("realname");
String password = req.getParameter("mypassword");
}
In the html page code that calls the Servlet is:
在调用 Servlet 的 html 页面代码是:
<form action="identification" method="post" enctype="multipart/form-data">
User Name: <input type="text" name="realname">
Password: <input type="password" name="mypassword">
<input type="submit" value="Identification">
</form>
When I use method = "get"
in the Servlet, I get the value of id and password, however when using method = "post"
, id and password are set to null
. Why don't I get the values in this case?
当我method = "get"
在 Servlet 中使用时,我得到了 id 和 password 的值,但是在使用时method = "post"
,id 和密码设置为null
. 在这种情况下,为什么我没有得到值?
Another thing I'd like to know is how to use the data generated or validated by the Servlet. For example, if the Servlet shown above authenticates the user, I'd like to print the user id in my HTML page. I should be able to send the string 'id' as a response and use this info in my HTML page. Is it possible?
我想知道的另一件事是如何使用由 Servlet 生成或验证的数据。例如,如果上面显示的 Servlet 对用户进行身份验证,我想在我的 HTML 页面中打印用户 ID。我应该能够发送字符串“id”作为响应并在我的 HTML 页面中使用此信息。是否可以?
采纳答案by BalusC
Introduction
介绍
You should use doGet()
when you want to intercept on HTTP GET requests. You should use doPost()
when you want to intercept on HTTP POST requests. That's all. Do not port the one to the other or vice versa (such as in Netbeans' unfortunate auto-generated processRequest()
method). This makes no utter sense.
doGet()
当您想拦截HTTP GET 请求时,您应该使用。doPost()
当您想拦截HTTP POST 请求时应该使用。就这样。不要将一个移植到另一个,反之亦然(例如在 Netbeans 不幸的自动生成processRequest()
方法中)。这完全没有意义。
GET
得到
Usually, HTTP GET requests are idempotent. I.e. you get exactly the same result everytime you execute the request (leaving authorization/authentication and the time-sensitive nature of the page —search results, last news, etc— outside consideration). We can talk about a bookmarkable request. Clicking a link, clicking a bookmark, entering raw URL in browser address bar, etcetera will all fire a HTTP GET request. If a Servlet is listening on the URL in question, then its doGet()
method will be called. It's usually used to preprocessa request. I.e. doing some business stuff before presenting the HTML output from a JSP, such as gathering data for display in a table.
通常,HTTP GET 请求是幂等的。也就是说,每次执行请求时都会得到完全相同的结果(将授权/身份验证和页面的时间敏感特性——搜索结果、最新消息等——排除在外)。我们可以讨论一个可收藏的请求。单击链接、单击书签、在浏览器地址栏中输入原始 URL 等都会触发 HTTP GET 请求。如果 Servlet 正在侦听有问题的 URL,则将doGet()
调用其方法。它通常用于预处理请求。即在从 JSP 呈现 HTML 输出之前做一些业务工作,例如收集数据以显示在表格中。
@WebServlet("/products")
public class ProductsServlet extends HttpServlet {
@EJB
private ProductService productService;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Product> products = productService.list();
request.setAttribute("products", products); // Will be available as ${products} in JSP
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
}
}
<table>
<c:forEach items="${products}" var="product">
<tr>
<td>${product.name}</td>
<td><a href="product?id=${product.id}">detail</a></td>
</tr>
</c:forEach>
</table>
Also view/edit detail links as shown in last column above are usually idempotent.
上面最后一列中显示的查看/编辑详细信息链接通常是幂等的。
@WebServlet("/product")
public class ProductServlet extends HttpServlet {
@EJB
private ProductService productService;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Product product = productService.find(request.getParameter("id"));
request.setAttribute("product", product); // Will be available as ${product} in JSP
request.getRequestDispatcher("/WEB-INF/product.jsp").forward(request, response);
}
}
<dl>
<dt>ID</dt>
<dd>${product.id}</dd>
<dt>Name</dt>
<dd>${product.name}</dd>
<dt>Description</dt>
<dd>${product.description}</dd>
<dt>Price</dt>
<dd>${product.price}</dd>
<dt>Image</dt>
<dd><img src="productImage?id=${product.id}" /></dd>
</dl>
POST
邮政
HTTP POST requests are not idempotent. If the enduser has submitted a POST form on an URL beforehand, which hasn't performed a redirect, then the URL is not necessarily bookmarkable. The submitted form data is not reflected in the URL. Copypasting the URL into a new browser window/tab may not necessarily yield exactly the same result as after the form submit. Such an URL is then not bookmarkable. If a Servlet is listening on the URL in question, then its doPost()
will be called. It's usually used to postprocessa request. I.e. gathering data from a submitted HTML form and doing some business stuff with it (conversion, validation, saving in DB, etcetera). Finally usually the result is presented as HTML from the forwarded JSP page.
HTTP POST 请求不是幂等的。如果最终用户事先在未执行重定向的 URL 上提交了 POST 表单,则该 URL 不一定可添加书签。提交的表单数据不会反映在 URL 中。将 URL 复制粘贴到新的浏览器窗口/选项卡中可能不一定会产生与表单提交后完全相同的结果。这样的 URL 是不可添加书签的。如果 Servlet 正在侦听有问题的 URL,则将doPost()
调用它。它通常用于对请求进行后处理。即从提交的 HTML 表单中收集数据并用它做一些商业事情(转换、验证、保存在数据库中等)。最后,结果通常以来自转发的 JSP 页面的 HTML 形式呈现。
<form action="login" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="login">
<span class="error">${error}</span>
</form>
...which can be used in combination with this piece of Servlet:
...可以与这段 Servlet 结合使用:
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@EJB
private UserService userService;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userService.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user);
response.sendRedirect("home");
}
else {
request.setAttribute("error", "Unknown user, please try again");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
}
You see, if the User
is found in DB (i.e. username and password are valid), then the User
will be put in session scope (i.e. "logged in") and the servlet will redirect to some main page (this example goes to http://example.com/contextname/home
), else it will set an error message and forward the request back to the same JSP page so that the message get displayed by ${error}
.
你看,如果User
在 DB 中找到了(即用户名和密码有效),那么User
将被放入会话范围(即“登录”)并且 servlet 将重定向到某个主页(这个例子转到http://example.com/contextname/home
),否则它将设置一条错误消息并将请求转发回同一个 JSP 页面,以便通过${error}
.
You can if necessary also "hide" the login.jsp
in /WEB-INF/login.jsp
so that the users can only access it by the servlet. This keeps the URL clean http://example.com/contextname/login
. All you need to do is to add a doGet()
to the servlet like this:
如有必要,您还可以“隐藏” login.jsp
in,/WEB-INF/login.jsp
以便用户只能通过 servlet 访问它。这使 URL 保持干净http://example.com/contextname/login
。您需要做的就是doGet()
像这样向 servlet添加一个:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
}
(and update the same line in doPost()
accordingly)
(并相应地更新同一行doPost()
)
That said, I am not sure if it is just playing around and shooting in the dark, but the code which you posted doesn't look good (such as using compareTo()
instead of equals()
and digging in the parameternames instead of just using getParameter()
and the id
and password
seems to be declared as servlet instance variables — which is NOT threadsafe). So I would strongly recommend to learn a bit more about basic Java SE API using the Oracle tutorials(check the chapter "Trails Covering the Basics") and how to use JSP/Servlets the right way using those tutorials.
这就是说,我不知道这是否只是在玩周围,在黑暗中拍摄,但您发布的代码看起来并不好(如使用compareTo()
替代equals()
,并在parameternames挖掘,而不是仅仅使用getParameter()
和id
并password
似乎被声明为 servlet 实例变量——这不是线程安全的)。因此,我强烈建议您使用Oracle 教程(查看“涵盖基础知识的路径”一章)以及如何使用这些教程以正确的方式使用 JSP/Servlet来了解更多有关基本 Java SE API的知识。
See also:
也可以看看:
- Our servlets wiki page
- Java EE web development, where do I start and what skills do I need?
- Servlet returns "HTTP Status 404 The requested resource (/servlet) is not available"
- Show JDBC ResultSet in HTML in JSP page using MVC and DAO pattern
- 我们的 servlet 维基页面
- Java EE Web 开发,我从哪里开始,我需要什么技能?
- Servlet 返回“HTTP 状态 404 请求的资源 (/servlet) 不可用”
- 使用 MVC 和 DAO 模式在 JSP 页面中以 HTML 格式显示 JDBC ResultSet
Update: as per the update of your question (which is pretty major, you should not remove parts of your original question, this would make the answers worthless .. rather addthe information in a new block) , it turns out that you're unnecessarily setting form's encoding type to multipart/form-data
. This will send the request parameters in a different composition than the (default) application/x-www-form-urlencoded
which sends the request parameters as a query string (e.g. name1=value1&name2=value2&name3=value3
). You only need multipart/form-data
whenever you have a <input type="file">
element in the form to upload files which may be non-character data (binary data). This is not the case in your case, so just remove it and it will work as expected. If you ever need to upload files, then you'll have to set the encoding type so and parse the request body yourself. Usually you use the Apache Commons FileUploadthere for, but if you're already on fresh new Servlet 3.0 API, then you can just use builtin facilities starting with HttpServletRequest#getPart()
. See also this answer for a concrete example: How to upload files to server using JSP/Servlet?
更新:根据您的问题的更新(这是非常重要的,您不应该删除原始问题的部分内容,这会使答案毫无价值......而是将信息添加到新块中),事实证明您是不必要地将表单的编码类型设置为multipart/form-data
. 这将以与application/x-www-form-urlencoded
将请求参数作为查询字符串(例如name1=value1&name2=value2&name3=value3
)发送的(默认)不同的组合发送请求参数。你只需要multipart/form-data
当你有<input type="file">
表单中的元素上传文件,这些文件可能是非字符数据(二进制数据)。您的情况并非如此,因此只需将其删除,它就会按预期工作。如果您需要上传文件,则必须设置编码类型并自己解析请求正文。通常您在那里使用Apache Commons FileUpload,但如果您已经在使用全新的 Servlet 3.0 API,那么您可以使用以HttpServletRequest#getPart()
. 有关具体示例,另请参阅此答案:How to upload files to server using JSP/Servlet?
回答by Tom
Could it be that you are passing the data through get, not post?
可能是您通过 get 而不是 post 传递数据?
<form method="get" ..>
..
</form>
回答by Jay Hymanson
The servlet container's implementation of HttpServlet.service() method will automatically forward to doGet() or doPost() as necessary, so you shouldn't need to override the service method.
servlet 容器对 HttpServlet.service() 方法的实现将根据需要自动转发到 doGet() 或 doPost(),因此您不需要覆盖服务方法。
回答by S. Mayol
Both GET and POST are used by the browser to request a single resource from the server. Each resource requires a separate GET or POST request.
浏览器使用 GET 和 POST 来从服务器请求单个资源。每个资源都需要一个单独的 GET 或 POST 请求。
- The GET method is most commonly (and is the default method) used by browsers to retrieve information from servers. When using the GET method the 3rd section of the request packet, which is the request body, remains empty.
- 浏览器最常使用 GET 方法(也是默认方法)从服务器检索信息。使用 GET 方法时,请求数据包的第三部分(即请求正文)保持为空。
The GET method is used in one of two ways: When no method is specified, that is when you or the browser is requesting a simple resource such as an HTML page, an image, etc. When a form is submitted, and you choose method=GET on the HTML tag. If the GET method is used with an HTML form, then the data collected through the form is sent to the server by appending a "?" to the end of the URL, and then adding all name=value pairs (name of the html form field and value entered in that field) separated by an "&" Example: GET /sultans/shop//form1.jsp?name=Sam%20Sultan&iceCream=vanilla HTTP/1.0 optional headeroptional header<< empty line >>>
GET 方法用于以下两种方式之一: 未指定方法时,即您或浏览器正在请求简单的资源,例如 HTML 页面、图像等。 提交表单时,您选择方法=GET 在 HTML 标签上。如果 GET 方法用于 HTML 表单,则通过表单收集的数据通过附加“?”发送到服务器。到 URL 的末尾,然后添加以“&”分隔的所有名称=值对(html 表单字段的名称和在该字段中输入的值)示例:GET /sultans/shop//form1.jsp?name= Sam%20Sultan&iceCream=vanilla HTTP/1.0 optional headeroptional header<<空行>>>
The name=value form data will be stored in an environment variable called QUERY_STRING. This variable will be sent to a processing program (such as JSP, Java servlet, PHP etc.)
name=value 表单数据将存储在名为 QUERY_STRING 的环境变量中。这个变量会被发送到一个处理程序(如 JSP、Java servlet、PHP 等)
- The POST method is used when you create an HTML form, and request method=POST as part of the tag. The POST method allows the client to send form data to the server in the request body section of the request (as discussed earlier). The data is encoded and is formatted similar to the GET method, except that the data is sent to the program through the standard input.
- 创建 HTML 表单时使用 POST 方法,并请求 method=POST 作为标记的一部分。POST 方法允许客户端在请求的请求正文部分将表单数据发送到服务器(如前所述)。数据的编码和格式类似于 GET 方法,不同之处在于数据是通过标准输入发送到程序的。
Example: POST /sultans/shop//form1.jsp HTTP/1.0 optional headeroptional header<< empty line >>> name=Sam%20Sultan&iceCream=vanilla
示例:POST /sultans/shop//form1.jsp HTTP/1.0 optional headeroptional header<<空行>>> name=Sam%20Sultan&iceCream=vanilla
When using the post method, the QUERY_STRING environment variable will be empty. Advantages/Disadvantages of GET vs. POST
使用 post 方法时,QUERY_STRING 环境变量将为空。GET 与 POST 的优缺点
Advantages of the GET method: Slightly faster Parameters can be entered via a form or by appending them after the URL Page can be bookmarked with its parameters
GET 方法的优点: 稍快 可以通过表单输入参数,也可以将参数附加到 URL 页面之后,可以为其参数添加书签
Disadvantages of the GET method: Can only send 4K worth of data. (You should not use it when using a textarea field) Parameters are visible at the end of the URL
GET方式的缺点:只能发送4K的数据。(在使用 textarea 字段时不应使用它)参数在 URL 末尾可见
Advantages of the POST method: Parameters are not visible at the end of the URL. (Use for sensitive data) Can send more that 4K worth of data to server
POST 方法的优点: 参数在 URL 末尾不可见。(用于敏感数据)可以向服务器发送超过 4K 的数据
Disadvantages of the POST method: Can cannot be bookmarked with its data
POST方法的缺点:不能用它的数据做书签
回答by Uzair Zaman Sheikh
If you do <form action="identification" >
for your html form, data will be passed using 'Get' by default and hence you can catch this using doGet function in your java servlet code. This way data will be passed under the HTML header and hence will be visible in the URL when submitted.
On the other hand if you want to pass data in HTML body, then USE Post: <form action="identification" method="post">
and catch this data in doPost function. This was, data will be passed under the html body and not the html header, and you will not see the data in the URL after submitting the form.
如果您<form action="identification" >
为 html 表单执行此操作,默认情况下将使用“Get”传递数据,因此您可以在 java servlet 代码中使用 doGet 函数来捕获它。这样数据将在 HTML 标题下传递,因此在提交时将在 URL 中可见。另一方面,如果您想在 HTML 正文中传递数据,请使用 Post:<form action="identification" method="post">
并在 doPost 函数中捕获此数据。也就是说,数据将在 html 正文而不是 html 标题下传递,并且提交表单后您将看不到 URL 中的数据。
Examples from my html:
我的 html 中的示例:
<body>
<form action="StartProcessUrl" method="post">
.....
.....
Examples from my java servlet code:
我的 java servlet 代码中的示例:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
String surname = request.getParameter("txtSurname");
String firstname = request.getParameter("txtForename");
String rqNo = request.getParameter("txtRQ6");
String nhsNo = request.getParameter("txtNHSNo");
String attachment1 = request.getParameter("base64textarea1");
String attachment2 = request.getParameter("base64textarea2");
.........
.........