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

Servlet接收HTML表单空输入致数据库主键重复问题求助

问题:HTML表单输入限制失效,空值存入数据库引发主键重复错误

我通过HTML表单收集用户输入,使用Servlet将数据插入数据库。虽然在HTML代码中设置了输入格式限制,但空输入仍能被提交,第二次提交空字段时出现以下错误:
错误信息
Duplicate entry '' for key 'users.PRIMARY'
这表明用户名被以空字符串的形式存入了数据库,而用户名是主键,重复的空字符串触发了主键冲突。

原HTML表单代码

<form action="userreg" method="post">
    Username : <input type="text" name="username" pattern=".{3,}" title ="must contains more then 3 letters"><br/><br/>
    Password : <input type="password" name="password" placeholder="password must be 8 char long one upper, lower case letter must" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" title="Must have 8 chars one lowercase , uppercase"><br/><br/>
    FirstName: <input type="text" pattern=".{3,}" title="this field cant be empty" name="firstname"><br/><br/>
    Last Name: <input type="text" pattern=".{3,}" title="this field cant be empty" name="lastname"><br/><br/>
    Address : <input type="text"  pattern=".{3,}" name="address"><br/><br/>
    Phone No : <input type="text" pattern=".{3,}" name="phone"><br/><br/>
    Email Id : <input type="text" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" name="mailid" placeholder="xyz@gmail.com" title="please enter valid mail"><br/><br/>
    <input type="submit" value=" I AGREE FOR ALL TERMS & CONDITIONS ! REGISTER ME ">
</form>

原Servlet代码片段

try {
    Connection con = DBConnection.getCon();
    PreparedStatement ps = con
            .prepareStatement("insert into " + IUserContants.TABLE_USERS + "  values(?,?,?,?,?,?,?,?)");
    ps.setString(1, uName);
    ps.setString(2, pWord);
    ps.setString(3, fName);
    ps.setString(4, lName);
    ps.setString(5, addr);
    ps.setString(6, phNo);
    ps.setString(7, mailId);
    ps.setInt(8, 2);
    int k = ps.executeUpdate();         
    if (k==1) {
        RequestDispatcher rd = req.getRequestDispatcher("Sample.html");
        rd.include(req, res);
        pw.println("<h3 class='tab'>User Registered Successfully</h3>");
    } else {
        RequestDispatcher rd = req.getRequestDispatcher("Sample.html");
        pw.println("<h3 class='tab'>Registration failed !, please enter valid details</h3>");
        rd.include(req, res);               
        pw.println("Sorry for interruption! Register again");
    }
} catch (Exception e) {
    e.printStackTrace();
}

问题原因

  1. 前端验证不彻底:HTML的pattern属性仅做格式校验,但未设置required属性,用户可以直接提交空输入;且前端验证可被绕过(如禁用JavaScript、手动构造请求)。
  2. 后端无输入校验:Servlet直接将请求参数插入数据库,未对空值或不符合格式的数据做拦截,导致无效数据进入数据库。
  3. 数据库约束不足:用户名作为主键,未设置NOT NULL约束,允许空字符串存入。

解决方案

1. 前端强化验证:添加required属性

给所有必填输入框添加required属性,确保浏览器在提交前拦截空输入,配合pattern完成前端基础校验:

<form action="userreg" method="post">
    Username : <input type="text" name="username" pattern=".{3,}" title="必须包含至少3个字符" required><br/><br/>
    Password : <input type="password" name="password" placeholder="密码需8位以上,包含大小写字母和数字" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" title="密码必须8位以上,包含一个小写字母、一个大写字母" required><br/><br/>
    FirstName: <input type="text" pattern=".{3,}" title="此字段不能为空,至少3个字符" name="firstname" required><br/><br/>
    Last Name: <input type="text" pattern=".{3,}" title="此字段不能为空,至少3个字符" name="lastname" required><br/><br/>
    Address : <input type="text" pattern=".{3,}" name="address" required><br/><br/>
    Phone No : <input type="text" pattern=".{3,}" name="phone" required><br/><br/>
    Email Id : <input type="text" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" name="mailid" placeholder="xyz@gmail.com" title="请输入有效的邮箱地址" required><br/><br/>
    <input type="submit" value=" 我同意所有条款!注册账号 ">
</form>

2. 后端添加输入校验(核心)

前端验证无法完全信任,必须在Servlet层添加校验逻辑,拦截无效数据后再执行数据库操作:

// 先获取并修剪请求参数
String uName = req.getParameter("username") != null ? req.getParameter("username").trim() : "";
String pWord = req.getParameter("password") != null ? req.getParameter("password").trim() : "";
String fName = req.getParameter("firstname") != null ? req.getParameter("firstname").trim() : "";
String lName = req.getParameter("lastname") != null ? req.getParameter("lastname").trim() : "";
String addr = req.getParameter("address") != null ? req.getParameter("address").trim() : "";
String phNo = req.getParameter("phone") != null ? req.getParameter("phone").trim() : "";
String mailId = req.getParameter("mailid") != null ? req.getParameter("mailid").trim() : "";

// 输入合法性校验
boolean isValid = true;
String errorMsg = "";
if(uName.isEmpty() || uName.length() < 3){
    errorMsg += "用户名不能为空,且至少3个字符<br/>";
    isValid = false;
}
if(pWord.isEmpty() || !pWord.matches("(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,}")){
    errorMsg += "密码不能为空,需8位以上且包含大小写字母和数字<br/>";
    isValid = false;
}
if(fName.isEmpty() || fName.length() < 3){
    errorMsg += "名字不能为空,且至少3个字符<br/>";
    isValid = false;
}
if(lName.isEmpty() || lName.length() < 3){
    errorMsg += "姓氏不能为空,且至少3个字符<br/>";
    isValid = false;
}
if(addr.isEmpty() || addr.length() < 3){
    errorMsg += "地址不能为空,且至少3个字符<br/>";
    isValid = false;
}
if(phNo.isEmpty() || phNo.length() < 3){
    errorMsg += "手机号不能为空,且至少3个字符<br/>";
    isValid = false;
}
if(mailId.isEmpty() || !mailId.matches("[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$")){
    errorMsg += "请输入有效的邮箱地址<br/>";
    isValid = false;
}

// 校验不通过,返回错误提示
if(!isValid){
    RequestDispatcher rd = req.getRequestDispatcher("Sample.html");
    pw.println("<h3 class='tab'>注册失败!</h3>");
    pw.println("<p>" + errorMsg + "</p>");
    rd.include(req, res);               
    pw.println("请重新填写注册信息");
    return;
}

// 校验通过,执行数据库插入
try {
    Connection con = DBConnection.getCon();
    PreparedStatement ps = con.prepareStatement("insert into " + IUserContants.TABLE_USERS + " values(?,?,?,?,?,?,?,?)");
    ps.setString(1, uName);
    ps.setString(2, pWord);
    ps.setString(3, fName);
    ps.setString(4, lName);
    ps.setString(5, addr);
    ps.setString(6, phNo);
    ps.setString(7, mailId);
    ps.setInt(8, 2);
    int k = ps.executeUpdate();         
    if (k == 1) {
        RequestDispatcher rd = req.getRequestDispatcher("Sample.html");
        rd.include(req, res);
        pw.println("<h3 class='tab'>用户注册成功</h3>");
    } else {
        RequestDispatcher rd = req.getRequestDispatcher("Sample.html");
        pw.println("<h3 class='tab'>注册失败!请检查输入信息</h3>");
        rd.include(req, res);               
        pw.println("请重新尝试注册");
    }
} catch (Exception e) {
    e.printStackTrace();
    // 捕获主键重复等数据库异常,返回友好提示
    RequestDispatcher rd = req.getRequestDispatcher("Sample.html");
    pw.println("<h3 class='tab'>注册失败!用户名已存在或系统异常</h3>");
    rd.include(req, res);               
}

3. 数据库层面加固

修改用户表结构,给用户名字段添加NOT NULL约束,从数据库层面防止空值插入:

ALTER TABLE users MODIFY COLUMN username VARCHAR(50) NOT NULL PRIMARY KEY;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:05:13