J2EE项目中点击提交按钮后页面无法正确加载数据库数据的问题排查
看起来你遇到的问题是提交表单更新数据库后,页面没有重新加载最新的数据库数据对吧?我来帮你梳理下问题所在和解决办法:
问题根源
你的servletProject2中,doGet方法会从数据库查询最新的学生(etudiants)和团队(ekips)数据,将其存入request属性后再转发到ekip.jsp,这也是页面能正确显示初始数据的原因。
但在doPost方法中,你完成数据库更新操作后,直接将请求转发到了ekip.jsp,没有重新执行数据库查询并更新request中的属性。此时JSP拿到的还是旧的request数据(甚至可能因为转发的是POST请求,request里没有加载新数据的属性),所以页面显示异常。
解决方案
这里推荐两种符合Web开发最佳实践的解决方式,你可以根据需求选择:
方案一:采用Post/Redirect/Get(PRG)模式(更推荐)
这是Web开发中避免表单重复提交、确保页面数据最新的标准模式:在doPost处理完数据库操作后,重定向到当前Servlet,触发doGet方法重新加载数据。
你之前尝试重定向但失败,大概率是路径问题。需要确保重定向的路径是Servlet的映射地址,比如如果你的Servlet使用@WebServlet("/servletProject2")注解,修改doPost的结尾代码如下:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 原有的表单处理逻辑... String prenomNom = request.getParameter("selectEtudiant"); String[] tabpn = prenomNom.split(" "); String prenom = tabpn[0]; String nom = tabpn[1]; AjEtuEkip ajEtuEkip = new AjEtuEkip(); try { ajEtuEkip.ajouterEtuEkip(prenom, nom, Integer.parseInt(request.getParameter("valueEkip"))); // 重定向到当前Servlet,触发doGet response.sendRedirect(request.getContextPath() + "/servletProject2"); return; // 重定向后不需要再执行后续代码 } catch (NumberFormatException | SQLException e) { e.printStackTrace(); System.out.println("Problème ajout"); } // 如果出现异常,也可以选择加载数据后转发,或者重定向到错误页面 Utilisateur tableEtudiant = new Utilisateur(); request.setAttribute("etudiants", tableEtudiant.recupererEtudiant()); Ekips tableEkip = new Ekips(); request.setAttribute("ekips", tableEkip.recupererEkip()); this.getServletContext().getRequestDispatcher("/WEB-INF/ekip.jsp").forward(request, response); }
重定向后,浏览器会发送一个新的GET请求到Servlet,doGet方法会执行数据库查询并将最新数据传入JSP,页面就能正常显示了。
方案二:在doPost中复用数据加载逻辑
如果不想使用重定向,可以把doGet中的数据加载逻辑抽成公共方法,在doPost处理完更新后调用该方法,更新request属性后再转发到JSP:
// 抽取出公共的数据库数据加载方法 private void loadData(HttpServletRequest request) throws ServletException { Utilisateur tableEtudiant = new Utilisateur(); request.setAttribute("etudiants", tableEtudiant.recupererEtudiant()); Ekips tableEkip = new Ekips(); request.setAttribute("ekips", tableEkip.recupererEkip()); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { loadData(request); this.getServletContext().getRequestDispatcher("/WEB-INF/ekip.jsp").forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 原有的表单处理逻辑... String prenomNom = request.getParameter("selectEtudiant"); String[] tabpn = prenomNom.split(" "); String prenom = tabpn[0]; String nom = tabpn[1]; AjEtuEkip ajEtuEkip = new AjEtuEkip(); try { ajEtuEkip.ajouterEtuEkip(prenom, nom, Integer.parseInt(request.getParameter("valueEkip"))); } catch (NumberFormatException | SQLException e) { e.printStackTrace(); System.out.println("Problème ajout"); } // 调用公共方法加载最新数据 loadData(request); this.getServletContext().getRequestDispatcher("/WEB-INF/ekip.jsp").forward(request, response); }
这样doPost处理完数据库更新后,会重新获取最新的学生和团队数据,转发到JSP时就能显示正确内容了。
额外优化建议
- 你的JSP中有两个
method="post"的表单,但第一个选择团队数量的表单没有提交按钮,若需要处理该表单的提交,记得在doPost中添加对应的逻辑。 - 目前通过学生姓名(
selectEtudiant的value是姓名)来拆分获取姓和名的方式不可靠,如果学生姓名包含空格(比如中间名)会导致错误。建议将option的value改为学生ID:<option value="${ etudiant.id }"><c:out value="${ etudiant.prenom }"/> <c:out value="${ etudiant.nom }"/></option>,然后在Servlet中通过ID查询对应的学生,这样逻辑更健壮。
备注:内容来源于stack exchange,提问作者Maxxss

