iT邦幫忙

2026 iThome 鐵人賽

0
JavaScript

30天從零打造醫療資訊小系統系列 第 21 篇

Day 24|避免錯誤資料進入資料庫:建立表單驗證機制

  • 分享至 

  • xImage
  •  

一、為什麼表單需要驗證?

在前面的文章中,我們已經完成病患資料的新增、查詢、修改、刪除與搜尋。

但我們還沒有認真處理一個問題:

如果使用者輸入錯誤的資料,系統該怎麼辦?

例如:

  • 姓名沒有填寫。
  • 生日格式錯誤。
  • 電話欄位輸入不合理的內容。
  • 使用者繞過網頁表單,直接送出不符合規則的請求。

如果系統沒有檢查,就可能把錯誤資料寫入資料庫。

因此,今天要學習表單驗證,讓系統在儲存資料之前先確認輸入是否符合基本規則。

二、表單驗證分成兩個部分

常見的表單驗證可以分成兩種。

  1. 前端驗證

前端驗證是在瀏覽器中進行的,例如 HTML 的 required、type="date" 和 maxlength。

這些屬性可以協助使用者在送出表單前發現部分錯誤。

但前端驗證可以被繞過,因此不能只靠它保護資料庫。

  1. 後端驗證

後端驗證是在 Servlet 或其他伺服器端程式中進行。

例如:

String name = request.getParameter("name");
if (name == null || name.isBlank()) {
// 拒絕儲存
}

即使使用者繞過前端表單,伺服器仍然會再次檢查輸入。

因此,前端驗證主要是改善使用體驗,後端驗證才是資料儲存前不可省略的檢查。

三、先建立有驗證功能的表單

我們先建立 patient-form.jsp:

<%@ page contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>

這裡使用 required 要求姓名與生日不可空白,也使用 pattern 對電話輸入進行基本格式限制。

不過,不同地區的電話格式可能不同,因此這個範例只是教學用途,並不是完整的國際電話驗證規則。

四、在 Servlet 進行後端驗證

接下來建立 PatientRegisterServlet.java。

這個範例會接收表單資料、驗證姓名和生日,再將合法資料寫入 MySQL。

package servlet;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.regex.Pattern;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import util.DBConnection;
@WebServlet("/patient/register")
public class PatientRegisterServlet extends HttpServlet {
private static final Pattern PHONE_PATTERN =
Pattern.compile("[0-9+\- ]{6,20}");
@Override
protected void doPost(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
String gender = request.getParameter("gender");
String birthdayText = request.getParameter("birthday");
String phone = request.getParameter("phone");
name = name == null ? "" : name.trim();
gender = gender == null ? "" : gender.trim();
birthdayText = birthdayText == null
? "" : birthdayText.trim();
phone = phone == null ? "" : phone.trim();
String error = null;
LocalDate birthday = null;
if (name.isBlank()) {
error = "姓名不可為空白。";
} else if (name.length() > 100) {
error = "姓名長度不可超過 100 個字元。";
}
if (error == null) {
try {
birthday = LocalDate.parse(birthdayText);
if (birthday.isAfter(LocalDate.now())) {
error = "生日不可晚於今天。";
}
} catch (DateTimeParseException e) {
error = "生日格式不正確。";
}
}
if (error == null && !phone.isEmpty()
&& !PHONE_PATTERN.matcher(phone).matches()) {
error = "電話格式不正確。";
}
if (error != null) {
request.setAttribute("error", error);
request.getRequestDispatcher("/patient-error.jsp")
.forward(request, response);
return;
}
String sql = "INSERT INTO patient "
+ "(name, gender, birthday, phone) "
+ "VALUES (?, ?, ?, ?)";
try (
Connection conn = DBConnection.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)
) {
ps.setString(1, name);
ps.setString(2, gender);
ps.setDate(
3,
java.sql.Date.valueOf(birthday)
);
if (phone.isEmpty()) {
ps.setNull(4, java.sql.Types.VARCHAR);
} else {
ps.setString(4, phone);
}
ps.executeUpdate();
response.sendRedirect(
request.getContextPath() + "/patients"
);
} catch (SQLException e) {
throw new ServletException("新增病患資料失敗", e);
}
}
}

這裡的驗證規則包含:

  1. 姓名不可空白。
  2. 姓名長度不可超過資料表欄位限制。
  3. 生日必須符合日期格式。
  4. 生日不可晚於今天。
  5. 電話如果有填寫,就必須符合這份範例設定的格式。

請注意,這份範例以先前的 patient 資料表為基礎。若你的資料表欄位、長度或必填規則不同,應同步調整程式。

五、顯示錯誤訊息

當輸入資料不符合規則時,Servlet 會將錯誤訊息傳給 JSP。

建立 patient-error.jsp:

<%@ page contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ taglib prefix="c"
uri="jakarta.tags.core" %>

這樣一來,使用者就能知道是哪個欄位出了問題,而不是只看到一個沒有說明的錯誤畫面。

這個版本會在驗證失敗後顯示錯誤訊息,返回表單時需要重新輸入。如果想進一步改善體驗,可以把原本輸入的內容也保留下來。

六、如何測試驗證功能?

啟動 Tomcat 後,開啟新增病患表單。

可以依序測試以下情況:

測試內容 預期結果
姓名留空 阻止送出或顯示錯誤
生日格式不正確 顯示日期格式錯誤
生日設定為未來日期 顯示生日不可晚於今天
電話輸入不符合規則的內容 顯示電話格式錯誤
輸入符合規則的測試資料 新增成功並回到清單

除了透過瀏覽器測試,也可以思考:如果有人不使用這個 HTML 表單,而是直接發送請求,後端是否仍然能拒絕不合法的資料?

這就是後端驗證的價值。

七、驗證不只是檢查有沒有填寫

實際的醫療資訊系統可能還需要考慮:

  • 欄位長度是否符合資料庫設計。
  • 日期與數值是否在合理範圍。
  • 使用者是否有權限新增或修改資料。
  • 輸入內容是否可能造成 SQL Injection 或跨站腳本攻擊。
  • 錯誤訊息是否暴露敏感資訊。
  • 資料是否需要額外的業務規則檢查。

不同欄位應該有不同的驗證規則,不能只用一個 required 解決所有問題。

今日小結

今天我們完成了基本的表單驗證機制,學會:

  1. 使用 HTML 屬性進行前端驗證。
  2. 在 Servlet 取得並檢查表單參數。
  3. 使用 LocalDate 驗證日期。
  4. 使用正規表示式檢查電話格式。
  5. 驗證失敗時顯示錯誤訊息。
  6. 只有通過驗證後,才執行資料庫新增操作。

Day 24 完成!

現在我們的系統除了能管理病患資料,也開始具備基本的輸入檢查。接下來可以繼續完成登入功能與權限管理,讓系統逐步接近一個完整的醫療資訊小系統。

參考資料:Jakarta Servlet 官方文件


上一篇
Day 23|從病患清單進入詳細資料:使用 Servlet 與 JSP 顯示單筆紀錄
下一篇
Day 25|整理程式碼:把資料庫操作獨立成 DAO
系列文
30天從零打造醫療資訊小系統 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言