介绍
当你想要拦截HTTP GET请求时,你应该使用doGet()。
当你想要拦截HTTP POST请求时,你应该使用doPost()。
就这样。不要将一个移植到另一个,反之亦然(例如在 Netbeans 不幸的自动生成方法中)。这是完全没有道理的。processRequest()
获取
通常,HTTP GET 请求是幂等的。也就是说,每次执行请求时都会得到完全相同的结果(将授权/身份验证和页面的时间敏感性 ( 搜索结果,最新消息等 - 留在考虑范围之外)。我们可以讨论一个可添加书签的请求。单击链接,单击书签,在浏览器地址栏中输入原始URL等都将触发HTTP GET请求。如果 Servlet 正在侦听有问题的 URL,则将调用其方法。它通常用于预处理请求。即,在呈现来自 JSP 的 HTML 输出之前做一些业务工作,例如收集数据以在表中显示。doGet()
@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);
}
}
请注意,JSP 文件被显式放置在文件夹中,以防止最终用户能够在不调用预处理 servlet 的情况下直接访问它(因此最终因看到空表而感到困惑)。/WEB-INF
<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>
此外,如上一列所示,查看/编辑详细信息链接通常是幂等的。
@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>
发布
HTTP POST 请求不是幂等的。如果最终用户事先在 URL 上提交了 POST 表单,而该表单尚未执行重定向,则该 URL 不一定是可添加书签的。提交的表单数据不会反映在 URL 中。将 URL 复制粘贴到新的浏览器窗口/选项卡中不一定会产生与表单提交后完全相同的结果。这样一个 URL 是不可添加书签的。如果 Servlet 正在侦听有问题的 URL,则将调用它。它通常用于对请求进行后处理。即,从提交的HTML表单中收集数据并对其进行一些业务处理(转换,验证,保存在数据库中等)。最后,通常结果从转发的JSP页面显示为HTML。doPost()
<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>
...这可以与这块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);
}
}
}
你看,如果在 DB 中找到 (即用户名和密码是有效的),那么 将放在会话范围内(即“已登录”),并且 servlet 将重定向到某个主页(此示例转到 ),否则它将设置一条错误消息并将请求转发回相同的 JSP 页面,以便消息由 显示。User
User
http://example.com/contextname/home
${error}
如有必要,您还可以“隐藏”in,以便用户只能通过 servlet 访问它。这将使 URL 保持干净。您需要做的就是像这样向 servlet 添加一个:login.jsp
/WEB-INF/login.jsp
http://example.com/contextname/login
doGet()
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
}
(并相应地更新 doPost()
中的同一行)
也就是说,我不确定它是否只是在黑暗中玩耍和射击,但是您发布的代码看起来并不好(例如使用而不是挖掘参数名称,而不仅仅是使用和和似乎被声明为servlet实例变量 - 这不是线程安全的)。因此,我强烈建议使用Oracle教程(查看“覆盖基础知识的Trails”一章)学习更多关于基本Java SE API的知识,以及如何使用这些教程以正确的方式使用JSP / Servlets。compareTo()
equals()
getParameter()
id
password
另请参阅:
更新:根据您问题的更新(这是非常主要的,您不应该删除原始问题的一部分,这将使答案毫无价值......而是将信息添加到新块中),事实证明您不必要地将表单的编码类型设置为多部分/表单数据
。这将以与(默认)不同的组合发送请求参数,后者将请求参数作为查询字符串(例如)发送。只有当表单中有一个元素时,您才需要上传可能是非字符数据(二进制数据)的文件。在您的案例中,情况并非如此,因此只需将其删除,它就会按预期工作。如果您需要上传文件,则必须设置编码类型并自行解析请求正文。通常你在那里使用Apache Commons FileUpload,但是如果你已经在使用全新的Servlet 3.0 API,那么你可以使用从HttpServletRequest#getPart()
开始的内置工具。另请参阅此答案以获取具体示例:如何使用 JSP/Servlet 将文件上载到服务器?application/x-www-form-urlencoded
name1=value1&name2=value2&name3=value3
multipart/form-data
<input type="file">