
在web应用中,用户通过html表单(<form>元素)向服务器提交数据。表单的核心属性包括:
客户端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()。如果验证通过,则允许表单的默认提交行为发生,让浏览器按照 <form method="post" action="LoginServlet"> 的定义向 LoginServlet 发送POST请求。
建议监听表单的 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 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号