You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

doPost方法无法获取请求属性,出现NullPointerException问题排查

问题分析与解决方案

兄弟,我一眼就看出问题所在了——HTTP是无状态协议,你遇到的NullPointerException本质是因为doGet和doPost是两次完全独立的HTTP请求,它们对应的HttpServletRequest对象完全不一样,所以你在doGet里设置的request属性,到doPost请求时早就不存在了!

为什么会出现这个问题?

  • request.setAttribute()存储的属性,生命周期只限于当前请求:你在doGet里把foo存到request里,只能在这次GET请求的转发/包含过程中使用(比如你forward到updatefoo.jsp时能拿到),但当用户在jsp里提交表单触发POST请求时,这已经是一个全新的request对象,之前的属性自然就丢失了。
  • 你说存session也无效?大概率是你存session的方式有问题,或者会话被意外销毁了(比如浏览器重启、会话超时),正常情况下session是跨请求保留的。

两种可行的解决方案

方案一:用Session跨请求存储Foo对象(适合需要保留完整对象的场景)

修改doGet方法,把foo存到session中,而不是request:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        int id = Integer.parseInt(request.getParameter("id"));
        Foo foo = fooDao.getFooById(id);
        System.out.println(foo.toString());
        // 将foo存入session,跨请求保留
        request.getSession().setAttribute("foo", foo);
        // 建议用forward而不是include,更符合页面跳转的逻辑
        RequestDispatcher dispatcher = request.getRequestDispatcher("updatefoo.jsp");
        dispatcher.forward(request, response);
    } catch (NumberFormatException e) {
        // 处理ID格式错误的情况,比如跳回列表页
        response.sendRedirect("fooList.jsp");
    }
}

然后在doPost方法中从session获取,用完记得移除避免内存占用:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    HttpSession session = request.getSession(false); // 不自动创建新session
    if (session != null) {
        Foo notUpdatedFoo = (Foo) session.getAttribute("foo");
        if (notUpdatedFoo != null) {
            System.out.println(notUpdatedFoo.toString());
            // 这里可以获取表单提交的新数据,更新foo对象后调用DAO保存
            // fooDao.updateFoo(notUpdatedFoo);
            
            // 用完立即移除session中的foo,避免内存泄漏
            session.removeAttribute("foo");
            // 跳转到成功页面或列表页
            response.sendRedirect("fooList.jsp");
        } else {
            // 处理foo不存在的情况
            response.sendRedirect("fooList.jsp");
        }
    } else {
        // 会话失效,比如用户未登录,跳转到登录页
        response.sendRedirect("login.jsp");
    }
}

方案二:在表单中传递Foo的ID(轻量无状态方案,更推荐)

既然最终你需要的是Foo的ID来更新,其实可以不用存对象,直接在updatefoo.jsp的表单里加一个隐藏域传递ID,然后在doPost中重新从数据库查询Foo:

<form action="UpdateFooServlet" method="post">
    <!-- 你的其他表单字段,比如foo的名称、描述等 -->
    <input type="hidden" name="fooId" value="${foo.id}">
    <button type="submit">更新Foo</button>
</form>

修改doPost方法,通过ID重新查询Foo:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        int fooId = Integer.parseInt(request.getParameter("fooId"));
        Foo notUpdatedFoo = fooDao.getFooById(fooId);
        if (notUpdatedFoo != null) {
            System.out.println(notUpdatedFoo.toString());
            // 获取表单提交的新数据,更新foo对象
            // notUpdatedFoo.setName(request.getParameter("name"));
            // fooDao.updateFoo(notUpdatedFoo);
            
            response.sendRedirect("fooList.jsp");
        } else {
            response.sendRedirect("fooList.jsp");
        }
    } catch (NumberFormatException e) {
        response.sendRedirect("fooList.jsp");
    }
}

额外注意事项

  • 尽量避免用include跳转页面,forward更符合页面跳转的业务逻辑;
  • 处理Integer.parseInt()时一定要加异常捕获,防止用户传递非法ID导致程序崩溃;
  • 用session存储对象时,务必在使用后移除,避免会话内存占用过高。

内容的提问来源于stack exchange,提问作者jimmyrap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:16:43