问题
我开发了一个将信息发送到Servlet的HTML页面。在Servlet中,我使用的方法是doGet()
和28892036:
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");
}
在调用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>
当我在Servlet中使用method = "get"
时,我得到了id和密码的值,但是当使用method = "post"
时,id和密码设置为null
。为什么我不能在这种情况下获得值?
我想知道的另一件事是如何使用Servlet生成或验证的数据。例如,如果上面显示的Servlet对用户进行身份验证,我想在HTML页面中打印用户ID。我应该能够将字符串'id'作为响应发送,并在我的HTML页面中使用此信息。可能吗?
#1 热门回答(181 赞)
介绍
你想拦截HTTP GET requests时应该使用doGet()
。当你想拦截HTTP POST requests时,你应该使用doPost()
。就这样。不要将一个移植到另一个,反之亦然(例如在Netbeans的不幸自动生成的processRequest()
方法中)。这没有任何意义。
GET
通常,HTTP GET请求是idempotent。即每次执行请求时都会得到完全相同的结果(保留授权/身份验证以及页面搜索结果的时间敏感性,最后新闻等 - 在考虑之外)。我们可以谈论可收藏的请求。单击链接,单击书签,在浏览器地址栏中输入原始URL,等等都将触发HTTP GET请求。如果Servlet正在侦听相关URL,则将调用其doGet()
方法。它通常用于预处理a请求。即在从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>
同样查看/编辑上面最后一栏中显示的详细链接通常也是幂等的。
@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请求不是幂等的。如果最终用户事先在URL上提交了POST表单(尚未执行重定向),则该URL不一定是可收藏的。提交的表单数据不会反映在URL中。将URL复制到新的浏览器窗口/选项卡可能不一定会产生与表单提交后完全相同的结果。这样的URL因此不可收藏。如果Servlet正在侦听有问题的URL,那么将调用它的doPost()
。它通常用于后处理a请求。即从提交的HTML表单中收集数据并用它做一些业务(转换,验证,保存在DB等)。最后,结果通常是从转发的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);
}
}
}
你看,如果在DB中找到User
(即用户名和密码有效),那么User
将被放入会话范围(即"登录")并且servlet将重定向到某个主页面(此示例转到http://example.com/contextname/home
),否则它将设置错误消息并将请求转发回同一个JSP页面,以便消息显示${error}
。
如果需要,你还可以"隐藏"用户只能通过servlet访问它的login.jsp
in/WEB-INF/login.jsp
。这使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()
更新同一行)
也就是说,我不确定它是否只是在黑暗中玩耍和拍摄,但是你发布的代码看起来并不好(例如使用411652194而不是equals()
并且在参数名称中挖掘而不是仅仅使用getParameter()
和id
和password
似乎被声明为servlet实例变量 - 这是NOTthreadsafe)。因此,我强烈建议你使用Oracle tutorials了解更多有关基本Java SE API的信息(请参阅"Trails Covering the Basics"一章)以及如何使用those tutorials以正确的方式使用JSP / Servlet。
也可以看看:
- 我们的servlets维基页面
- Java EE Web开发,我从哪里开始,我需要什么技能?
- Servlet返回"HTTP状态404请求的资源(/ servlet)不可用"
- 使用MVC和DAO模式在JSP页面中以HTML格式显示JDBC ResultSet
更新:根据你的问题的更新(这是非常重要的,你不应该删除原始问题的部分,这将使答案毫无价值..在新的区块中输入信息),事实证明你是不必要地将表单的编码类型设置为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?
#2 热门回答(2 赞)
浏览器使用GET和POST来从服务器请求单个资源。每个资源都需要单独的GET或POST请求。
- GET方法是浏览器用于从服务器检索信息的最常用(并且是默认方法)。使用GET方法时,请求数据包的第3部分(请求正文)保持为空。
GET方法有以下两种方式之一使用:当没有指定方法时,即你或浏览器请求简单资源(如HTML页面,图像等)时。提交表单时,你选择方法=获取HTML标记。如果GET方法与HTML表单一起使用,那么通过表单收集的数据将通过附加"?"发送到服务器。到URL的末尾,然后添加所有name = value对(html表单字段的名称和在该字段中输入的值),用"&"分隔示例:GET /sultans/shop//form1.jsp?name= Sam%20Sultan&iceCream = vanilla HTTP / 1.0可选的headeroptional标题<<空行>>>
name = value表单数据将存储在名为QUERY_STRING的环境变量中。该变量将被发送到处理程序(例如JSP,Java servlet,PHP等)。
- 创建HTML表单时使用POST方法,并请求method = POST作为标记的一部分。 POST方法允许客户端在请求的请求主体部分中将表单数据发送到服务器(如前所述)。除了通过标准输入将数据发送到程序之外,数据被编码并且格式化为类似于GET方法。
示例:POST /sultans/shop//form1.jsp HTTP / 1.0可选headeroptional标题<<空行>>> name = Sam%20Sultan&iceCream = vanilla
使用post方法时,QUERY_STRING环境变量将为空。 GET与POST的优点/缺点
GET方法的优点:稍微快一点的参数可以通过表单输入或者在URL页面可以用其参数加入书签后附加它们
GET方法的缺点:只能发送4K值的数据。 (使用textarea字段时不应使用它)参数在URL的末尾可见
POST方法的优点:参数在URL的末尾不可见。 (用于敏感数据)可以向服务器发送超过4K的数据
POST方法的缺点:无法将其数据加入书签
#3 热门回答(0 赞)
servlet容器的HttpServlet.service()方法的实现将根据需要自动转发到doGet()或doPost(),因此你不需要覆盖服务方法。