扫码关注官方订阅号
在web应用中,用户通过html表单(
客户端JavaScript验证则是在数据发送到服务器之前,对用户输入进行初步检查。这不仅能提供即时反馈,提升用户体验,还能有效减轻服务器的验证负担。只有当客户端验证通过后,数据才会被发送到服务器进行进一步处理(如服务器端验证、数据库操作等)。
原始代码中存在两个主要问题,导致JavaScript验证通过后无法正确调用Servlet:
在提供的JavaScript代码中,formSubmit.addEventListener("click", ...) 事件监听器在每次点击提交按钮时都会执行 e.preventDefault()。e.preventDefault() 的作用是阻止事件的默认行为。对于表单提交按钮而言,其默认行为就是提交表单。因此,无论客户端验证结果如何,表单的默认提交行为都被无条件阻止了,导致数据永远无法发送到 LoginServlet。
formSubmit.addEventListener("click", (e) => { // ... 验证逻辑 ... if (Rno == null || Rno == "" || Password.length < 7) { alert("Please enter a Room No or your password is incorrect"); setTimeout(function () { window.location.reload(); }, 5000); } e.preventDefault(); // 问题所在:无条件阻止了表单提交 })
当尝试使用 document.location.href = 'LoginServlet'; 进行跳转时,浏览器会发起一个HTTP GET请求。然而,LoginServlet 中只实现了 doPost 方法来处理POST请求,没有实现 doGet 方法。当服务器收到一个POST-only Servlet的GET请求时,根据HTTP协议规范,会返回HTTP 405 Method Not Allowed 错误,表示请求的HTTP方法不被允许。
立即学习“Java免费学习笔记(深入)”;
public class LoginServlet extends HttpServlet { // ... protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 实现了doPost方法 } // 没有实现doGet方法 }
解决上述问题的关键在于有条件地阻止表单的默认提交行为。只有当客户端验证失败时,才调用 e.preventDefault()。如果验证通过,则允许表单的默认提交行为发生,让浏览器按照
ai绘图提示词免费分享
建议监听表单的 submit 事件而非按钮的 click 事件,因为 submit 事件能捕获所有表单提交方式(例如用户按回车键)。
<script> // 获取表单元素,而不是提交按钮 const loginForm = document.querySelector(".loginForm"); loginForm.addEventListener("submit", (e) => { // 监听表单的submit事件 const Rno = document.getElementById("Rno").value; const Password = document.getElementById("pass").value; if (Rno === null || Rno.trim() === "" || Password.length < 7) { alert("请输入房间号,或密码长度不正确(至少7位)。"); // 仅在验证失败时阻止表单的默认提交行为 e.preventDefault(); // 移除不必要的页面重载,因为它会清除用户输入,影响用户体验 // setTimeout(function () { window.location.reload(); }, 5000); } // 如果验证通过,不调用 e.preventDefault(),表单将正常以POST方式提交到LoginServlet }); </script>
注意事项:
LoginServlet 中的 doPost 方法已经基本正确地处理了POST请求。以下是完善和强调其关键点的最佳实践:
import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; // 建议在init方法中初始化数据库连接池或数据源,而不是在doPost中每次创建 // public void init() throws ServletException { ... } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置响应内容类型和字符编码,避免中文乱码 response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); Connection con = null; // 声明在try块外,以便finally中关闭 PreparedStatement ps = null; ResultSet rs = null; try { // 1. 加载数据库驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 2. 建立数据库连接 con = DriverManager.getConnection("jdbc:mysql://localhost:3306/student","root","root"); // 3. 获取并转换请求参数 String roomNoStr = request.getParameter("Roomno"); String password = request.getParameter("password"); // 参数空值检查(尽管前端已做,后端仍需再次验证,以防绕过前端) if (roomNoStr == null || roomNoStr.trim().isEmpty() || password == null || password.trim().isEmpty()) { out.println("房间号或密码不能为空。"); return; // 提前返回 } int roomNo; try { roomNo = Integer.parseInt(roomNoStr); } catch (NumberFormatException e) { out.println("房间号格式不正确,请输入数字。"); e.printStackTrace(); return; // 提前返回 } // 4. 使用PreparedStatement防止SQL注入 ps = con.prepareStatement("select roomNo, userName from login where roomNo=? and password=?"); ps.setInt(1, roomNo); ps.setString(2, password); // 5. 执行查询 rs = ps.executeQuery(); // 6. 处理查询结果 if(rs.next()) { // 登录成功 int userRoom = rs.getInt("roomNo"); // 推荐使用列名获取 String userName = rs.getString("userName"); // 推荐使用列名获取 out.println("登录成功!房间号: " + userRoom + " 分配给 " + userName); // 实际应用中,登录成功后通常会进行重定向或转发到用户主页 // request.getSession().setAttribute("loggedInUser", userName); // response.sendRedirect("welcome.jsp"); } else { // 登录失败 out.println("登录失败!房间号或密码不正确。"); } } catch (ClassNotFoundException e) { out.println("数据库驱动加载失败,请检查配置。"); e.printStackTrace(); } catch (SQLException e) { out.println("数据库操作异常,请稍后再试。"); e.printStackTrace(); } finally { // 7. 关闭资源,避免资源泄露 try { if (rs != null) rs.close(); if (ps != null) ps.close(); if (con != null) con.close(); } catch (SQLException e) { e.printStackTrace(); } if (out != null) out.close(); // 确保PrintWriter关闭 } } }
本文详细阐述了在Web应用中,如何正确地结合JavaScript客户端验证与Java Servlet后端处理来实现表单提交功能。核心要点在于:
遵循这些原则,开发者可以构建出既安全又用户友好的Web表单提交流程。
以上就是Web应用中JavaScript验证与Servlet表单提交的协同工作的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
微信扫码关注PHP中文网服务号
QQ扫码加入技术交流群
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
PHP学习
技术支持
返回顶部