Servlet中的doGet和doPost

时间:2010-02-28 01:02:41

标签: java servlets

我开发了一个将信息发送到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");
}

在调用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页面中使用此信息。有可能吗?

5 个答案:

答案 0 :(得分:188)

简介

如果要拦截doGet(),则应使用HTTP GET requests。如果要拦截doPost(),则应使用HTTP POST requests。就这样。不要将一个移植到另一个,反之亦然(例如在Netbeans的不幸的自动生成的processRequest()方法中)。这没有任何意义。

GET

通常,HTTP GET请求为idempotent。即每次执行请求时都会得到完全相同的结果(留下授权/身份验证以及页面搜索结果的时间敏感性,最后的新闻等 - 在考虑之外)。我们可以谈论可收藏的请求。单击链接,单击书签,在浏览器地址栏中输入原始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>

同样查看/编辑上面最后一栏中显示的详细链接通常也是幂等的。

@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()。它通常用于后处理请求。即从提交的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}显示消息。

如果需要,您还可以“隐藏”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()idpassword似乎被声明为servlet实例变量 - 它不是threadsafe)。因此,我强烈建议您使用Oracle tutorials了解有关基本Java SE API的更多信息(请参阅“Trails Covering the Basics”一章)以及如何使用those tutorials以正确的方式使用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?

答案 1 :(得分:2)

浏览器使用GET和POST来从服务器请求单个资源。每个资源都需要单独的GET或POST请求。

  1. GET方法是浏览器用于从服务器检索信息的最常见方式(也是默认方法)。使用GET方法时,请求数据包的第3部分(请求正文)仍为空。
  2. GET方法有两种使用方法: 如果没有指定方法,那么当您或浏览器请求简单资源(如HTML页面,图像等)时。 提交表单时,在HTML标记上选择method = GET。如果GET方法与HTML表单一起使用,那么通过表单收集的数据将通过附加“?”发送到服务器。到URL的末尾,然后添加所有name = value对(html表单字段的名称和在该字段中输入的值),以“&amp;”分隔 例: GET /sultans/shop//form1.jsp?name=Sam%20Sultan&iceCream=vanilla HTTP / 1.0可选的headeroptional标题&lt;&lt;空行&gt;&gt;&gt;

    name = value表单数据将存储在名为QUERY_STRING的环境变量中。 该变量将被发送到处理程序(例如JSP,Java servlet,PHP等)

    1. 创建HTML表单时使用POST方法,并请求method = POST作为标记的一部分。 POST方法允许客户端在请求的请求主体部分中将表单数据发送到服务器(如前所述)。除了数据通过标准输入发送到程序外,数据的编码和格式与GET方法类似。
    2. 实施例: POST /sultans/shop//form1.jsp HTTP / 1.0可选的headeroptional标题&lt;&lt;空行&gt;&gt;&gt; name = Sam%20Sultan&amp; iceCream = vanilla

      使用post方法时,QUERY_STRING环境变量将为空。 GET与POST的优点/缺点

      GET方法的优点: 稍快一些 可以通过表单输入参数,也可以在URL后附加参数 页面可以使用其参数添加书签

      GET方法的缺点: 只能发送4K值的数据。 (使用textarea字段时不应使用它) 参数在URL的末尾可见

      POST方法的优点: 参数在URL末尾不可见。 (用于敏感数据) 可以向服务器发送更多4K值的数据

      POST方法的缺点: 无法将其数据加入书签

答案 2 :(得分:0)

可能是你通过get传递数据,而不是发布?

<form method="get" ..>
..
</form>

答案 3 :(得分:0)

servlet容器的HttpServlet.service()方法的实现将根据需要自动转发到doGet()或doPost(),因此您不需要覆盖服务方法。

答案 4 :(得分:0)

如果为html表单执行<form action="identification" >,默认情况下将使用“Get”传递数据,因此您可以使用java servlet代码中的doGet函数捕获此数据。这样,数据将在HTML标头下传递,因此在提交时将在URL中显示。 另一方面,如果要在HTML正文中传递数据,请使用Post <form action="identification" method="post">并在doPost函数中捕获此数据。这样,数据将在html正文下传递,而不是html标题,并且在提交表单后你不会在URL中看到数据。

我的html示例:

<body>  
<form action="StartProcessUrl" method="post">
.....
.....

我的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");

.........
.........