Servlet中的doGet和doPost

ded*_*alo 105 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");
}
Run Code Online (Sandbox Code Playgroud)

在调用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> 
Run Code Online (Sandbox Code Playgroud)

当我method = "get"在Servlet中使用时,我获得了id和password的值,但是在使用时method = "post",id和password被设置为null.为什么我不能在这种情况下获得值?

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

Bal*_*usC 191

介绍

您应该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);
    }

}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

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

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

}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

...可以与这个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);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

你看,如果User在DB中找到(即用户名和密码有效),则会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);
}
Run Code Online (Sandbox Code Playgroud)

(并相应更新相同的行doPost())

也就是说,我不确定它是否只是在黑暗中玩耍和拍摄,但是你发布的代码看起来并不好(例如使用compareTo()equals()不是仅仅使用getParameter()和挖掘参数而不是idpassword似乎被声明为servlet实例变量 - 这不是线程安全的.因此,我强烈建议您使用Oracle教程学习更多有关基本Java SE API 的知识(请参阅"基础知识涵盖基础知识"一章)以及如何使用这些教程以正确的方式使用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().有关具体示例,请参阅此答案:如何使用JSP/Servlet将文件上载到服务器?


归档时间:

查看次数:

406031 次

最近记录:

8 年,11 月 前