介绍
当您想要拦截HTTP GET请求时,应使用doGet()
。当您想要拦截HTTP POST请求时,应使用doPost()
。就这样。不要将一个端口转移到另一个或反之亦然(例如在Netbeans的不幸自动生成的processRequest()
方法中)。这毫无意义。
GET
通常情况下,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);
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
}
}
请注意,JSP文件明确放置在
/WEB-INF
文件夹中,以防止最终用户直接访问它而不调用预处理servlet(从而最终看到一个空表格而感到困惑)。
<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);
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请求不具备幂等性。如果最终用户先前在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>
...这可以与此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);
}
}
}
如果在数据库中找到User
(即用户名和密码有效),则将User
放入会话范围(即“已登录”),并将servlet重定向到某个主页(此示例转到http://example.com/contextname/home
),否则它将设置错误消息并将请求转发回相同的JSP页面,以便通过${error}
显示消息。
如果需要,您还可以将login.jsp
“隐藏”在/WEB-INF/login.jsp
中,以便用户只能通过servlet访问它。这可以使URL保持干净:http://example.com/contextname/login
。您需要做的就是像这样为servlet添加一个doGet()
:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response)
}
(并相应更新doPost()
中的同一行)
话虽如此,我不确定这只是在摸索和盲目尝试,但你发布的代码看起来不太好(例如使用compareTo()
而非equals()
,挖掘参数名称而非仅使用getParameter()
,以及id
和password
似乎被声明为Servlet实例变量——这是不安全的线程)。因此,我强烈建议学习一些基本的Java SE API,使用Oracle教程(查看“覆盖基础知识的路径”章节),以及如何正确使用JSP/Servlets使用这些教程。
另请参阅:
更新:根据您问题的更新(这是相当重要的,您不应该删除原始问题的部分,否则答案将毫无价值..而是在新的块中
添加信息),结果表明您不必将表单的编码类型设置为
multipart/form-data
。这将以不同的组合方式发送请求参数,而(默认的)
application/x-www-form-urlencoded
将请求参数作为查询字符串发送(例如
name1=value1&name2=value2&name3=value3
)。只有在表单中有一个
<input type="file">
元素需要上传非字符数据(二进制数据)的文件时,才需要使用
multipart/form-data
。这在您的情况下并不适用,所以只需将其删除即可正常工作。如果您需要上传文件,则必须设置编码类型并自行解析请求体。通常情况下,您可以使用
Apache Commons FileUpload,但如果您已经使用最新的Servlet 3.0 API,则可以直接使用内置设施开始
HttpServletRequest#getPart()
。另请参见此答案,其中包含一个具体示例:
如何使用JSP/Servlet将文件上传到服务器?
enctype=multipart/form-data
吗?我怀疑这可能是你的问题所在。 - Jack Leow