Servlet中的doGet和doPost


105

我已经开发了一个HTML页面,该页面将信息发送到Servlet。在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> 

method = "get"在Servlet中使用时,我会获得id和password的值,但是在使用时method = "post",id和password会设置为null。为什么在这种情况下我无法获取值?

我想知道的另一件事是如何使用Servlet生成或验证的数据。例如,如果上面显示的Servlet对用户进行身份验证,我想在HTML页面中打印用户ID。我应该能够发送字符串“ id”作为响应,并在HTML页面中使用此信息。可能吗?


您如何在html中使用post方法?
伊戈尔·阿塔莫诺夫

而且,您需要什么使参数名称如此奇怪的循环?
伊戈尔·阿塔莫诺夫

1
您是否尝试过删除`enctype = multipart / form-data`?我怀疑那是你的问题。
杰克·利奥

就是这样 为什么不上班?谢谢你的帮助!
dedalo 2010年

Answers:


197

介绍

doGet()当您想拦截HTTP GET请求时应使用。doPost()当您想拦截HTTP POST请求时应使用。就这样。不要将一个移植到另一个,反之亦然(例如,在Netbeans不幸的自动生成processRequest()方法中)。这完全没有道理。

得到

通常,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>

同样,如上最后一列所示,查看/编辑详细信息链接通常也是幂等的。

@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,则将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);
        }
    }

}

您会看到,如果User在数据库中找到(即用户名和密码有效),则会User将其放入会话范围(即“登录”),并且servlet将重定向到某个主页(此示例转到http://example.com/contextname/home),否则它将设置一条错误消息,并将请求转发回同一JSP页面,以使该消息显示为${error}

如有必要,您也可以“隐藏”其中login.jsp/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);
}

(并相应地更新同一行doPost()

就是说,我不确定它是否只是在黑暗中玩耍而已,但是您发布的代码看起来并不好(例如使用compareTo()代替而不是equals()并挖掘参数名,而不是仅仅使用getParameter()and id和and password似乎被声明为servlet实例变量-不是threadsafe)。所以我强烈建议使用多了解一些关于基本的Java SE API 的Oracle教程(检查章“路线涵盖基础知识”)以及如何使用JSP / Servlet的使用正确的方法的教程

也可以看看:


更新:根据您的问题的更新(这是相当重要的,您不应该删除原始问题的一部分,这会使答案毫无价值..而是在新的块中添加信息),事实证明您是不必要将表单的编码类型设置为multipart/form-data。这将以与(默认)不同的构成发送请求参数,该(默认)application/x-www-form-urlencoded发送请求参数作为查询字符串(例如name1=value1&name2=value2&name3=value3)。你只需要multipart/form-data一有空就<input type="file">表单中的元素,以上传可能是非字符数据(二进制数据)的文件。您的情况并非如此,因此只需将其删除即可正常工作。如果您需要上传文件,则必须将编码类型设置为so,然后自己解析请求主体。通常,您在那里使用Apache Commons FileUpload,但是如果您已经在使用新的Servlet 3.0 API,那么您可以使用以开头的内置工具HttpServletRequest#getPart()。另请参见此答案以获取具体示例:如何使用JSP / Servlet将文件上传到服务器?


2

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

  1. GET方法是浏览器最常用(也是默认方法)从服务器检索信息的方法。使用GET方法时,请求数据包的第3部分(即请求正文)保持为空。

GET方法以两种方式之一使用:未指定任何方法时,即您或浏览器正在请求简单的资源(例如HTML页面,图像等)时。提交表单后,您选择方法在HTML标记上= GET。如果GET方法与HTML表单一起使用,则通过附加“?”将通过表单收集的数据发送到服务器。到URL的末尾,然后添加所有名称=值对(html表单字段的名称和在该字段中输入的值),并用“&”分隔。示例:GET /sultans/shop//form1.jsp?name= Sam%20Sultan&iceCream = vanilla HTTP / 1.0可选标头可选标头<<空行>>>

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

  1. 创建HTML表单时,将使用POST方法,并且将method = POST作为标记的一部分。POST方法允许客户端在请求的请求主体部分中将表单数据发送到服务器(如前所述)。数据的编码和格式类似于GET方法,不同之处在于数据是通过标准输入发送到程序的。

示例:POST /sultans/shop//form1.jsp HTTP / 1.0可选标头可选标头<<空行>>> name = Sam%20Sultan&iceCream = vanilla

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

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

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

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

POST方法的缺点:不能用其数据添加书签


0

Servlet容器的HttpServlet.service()方法的实现将根据需要自动转发到doGet()或doPost(),因此您不必重写service方法。


0

难道是您通过get而不是post传递数据?

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

0

如果您<form action="identification" >使用html表单,则默认情况下将使用“ 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");

.........
.........
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.