导航
电话
咨询
地图
顶部
在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方法不被允许。
public class LoginServlet extends HttpServlet { // ... protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 实现了doPost方法 } // 没有实现doGet方法 }
解决上述问题的关键在于有条件地阻止表单的默认提交行为。只有当客户端验证失败时,才调用 e.preventDefault()。如果验证通过,则允许表单的默认提交行为发生,让浏览器按照
建议监听表单的 submit 事件而非按钮的 click 事件,因为 submit 事件能捕获所有表单提交方式(例如用户按回车键)。
注意事项:
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表单提交流程。
# html # js # 前端 # json # go # win # word # javascript # java # 浏览器 # 中文乱码 # mysql
相关栏目: 【 行业资讯 】 【 网络运营 】 【 GEO优化 】 【 营销推广 】 【 SEO优化 】 【 技术教程 】 【 代码知识 】 【 AI推广 】
相关推荐: 如何使用Golang实现容器安全扫描_Golang Docker镜像漏洞检测方法 Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言 Win11怎样激活系统密钥_Win11系统密钥激活步骤【攻略】 如何理解Go指针和内存分配关系_Go Pointer内存Model解析 Mac怎么给文件夹加密_Mac创建加密磁盘映像教程【安全】 Go 语言标准库为何不提供泛型切片的 Contains 方法? Win11怎么开启窗口最小化到托盘_Win11部分应用隐藏任务栏图标减少干扰【方法】 Python脚本参数接收_sys与argparse解析【指导】 Win10怎样清理C盘浏览器缓存_Win10清理浏览器缓存步骤【步骤】 Python面向对象实战讲解_类与设计模式深入理解 如何提升Golang JSON序列化性能_Golang JSON编码效率优化方法 短链接怎么自定义还原php_修改解码规则适配需求【汇总】 Windows怎样关闭开始菜单推荐广告_Windows关闭开始菜单推荐设置【步骤】 Win11系统占用空间大怎么办 Win11深度瘦身清理指南【优化】 如何在 Go 中正确反序列化 XML 多节点数组(解决仅解析首个元素的问题) Mac如何彻底清理浏览器缓存?(Safari与Chrome) Win11如何更改鼠标滚轮速度 Win11调整滑轮滚动行数【设置】 php订单日志怎么记录评价_php记录订单评价日志方法【方法】 如何从 Go 的 map[string]interface{} 中安全获取值 如何在网页无标准表格标签时高效提取结构化数据 如何使用Golang捕获测试日志_Golang testing日志记录方法 如何在Golang中捕获HTTP服务器错误_GolangHTTP Handler中error处理 Linux如何挂载新硬盘_Linux磁盘分区格式化与开机自动挂载【指南】 PHP cURL GET请求:正确设置请求头与身份认证的完整教程 Win10怎样清理C盘阿里旺旺缓存_Win10清理阿里旺旺缓存步骤【步骤】 Win11讲述人怎么关闭_Win11误触开启语音朗读关闭【快捷键】 Windows蓝屏错误0x0000001E怎么修复_KMODEEXCEPTIONNOTHANDLED排查 php485读数据时阻塞怎么办_php485非阻塞读取设置技巧【详解】 Windows10如何更改鼠标灵敏度_Win10鼠标属性指针选项调节 如何使用Golang实现云原生应用弹性伸缩_自动应对流量变化 TestNG的testng.xml配置文件怎么写 Python大文件处理策略_内存优化说明【指导】 PHP接收参数值为空怎么办_判断和处理空参数方法说明【说明】 手机php怎么转mp4_手机端php文件转mp4app推荐【指南】 php本地部署后session无法保存_session存储路径与权限设置技巧【技巧】 Mac电脑进水了怎么办_MacBook进水后紧急处理方法【必看】 Win11怎么设置默认浏览器Chrome_Windows11修改默认网页打开方式 Win11怎么关闭自动调节亮度 Win11禁用内容自适应亮度【设置】 c++ std::future和std::promise c++线程间通信【教程】 Win10电脑怎么设置休眠快捷键_Windows10电源按钮功能定义 c++怎么编写动态链接库dll_c++ __declspec(dllexport)导出与调用【方法】 Win11怎么设置虚拟内存最佳大小_Windows11性能选项自定义分页文件 Win11文件扩展名怎么显示_Win11查看文件后缀名设置【基础】 Python多进程教程_multiprocessing模块实战 php文件怎么变mp4保存_php输出视频流保存为mp4操作【操作】 mac怎么查看wifi密码_MAC查看已连接WiFi密码方法【技巧】 如何使用Golang反射创建map对象_动态生成键值映射 如何在Golang中使用内置函数_Golanglen append make等使用技巧 Mac如何将HEIC图片格式转为JPG_Mac批量转换图片【指南】 如何在包含多值的列中精准搜索指定演员?
赣ICP备2024031479号