iT邦幫忙

2026 iThome 鐵人賽

0
JavaScript

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

Day 23|從病患清單進入詳細資料:使用 Servlet 與 JSP 顯示單筆紀錄

  • 分享至 

  • xImage
  •  

一、為什麼需要病患詳細資料頁面?

前幾篇文章中,我們已經完成病患清單、搜尋、修改和刪除功能。

不過,當使用者在清單中找到某一筆資料時,可能還需要查看這位病患的完整資訊。

如果把所有資訊都塞在清單裡,畫面不但容易變得擁擠,也不利於後續擴充。

因此,今天要新增一個功能:點選病患編號,就能進入該筆資料的詳細頁面。

這次我們會使用:

  • Servlet:接收病患編號並查詢資料。
  • JDBC:連接 MySQL。
  • PreparedStatement:安全地傳入查詢參數。
  • JSP:呈現病患詳細資料。

二、先認識單筆資料查詢

之前我們使用過:

SELECT id, name, gender, birthday, phone
FROM patient;

這個查詢會取得多筆資料。

如果只想查詢編號為 1 的病患,就可以加上 WHERE:

SELECT id, name, gender, birthday, phone
FROM patient
WHERE id = 1;

這樣就能取得指定編號的紀錄。

實際開發時,不應直接把使用者輸入的內容拼接到 SQL,而是透過參數化查詢處理。

三、建立 PatientDetailServlet

接下來建立 PatientDetailServlet.java。

這個 Servlet 會從網址取得病患編號,再向資料庫查詢對應的資料。

package servlet;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
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 model.Patient;
import util.DBConnection;
@WebServlet("/patient/detail")
public class PatientDetailServlet extends HttpServlet {
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String idText = request.getParameter("id");
int id;
try {
id = Integer.parseInt(idText);
if (id <= 0) {
throw new NumberFormatException();
}
} catch (NumberFormatException e) {
response.sendError(
HttpServletResponse.SC_BAD_REQUEST,
"病患編號格式不正確"
);
return;
}
String sql = "SELECT id, name, gender, birthday, phone "
+ "FROM patient WHERE id = ?";
Patient patient = null;
try (
Connection conn = DBConnection.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)
) {
ps.setInt(1, id);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
patient = new Patient(
rs.getInt("id"),
rs.getString("name"),
rs.getString("gender"),
rs.getDate("birthday"),
rs.getString("phone")
);
}
}
} catch (SQLException e) {
throw new ServletException("取得病患資料失敗", e);
}
if (patient == null) {
response.sendError(
HttpServletResponse.SC_NOT_FOUND,
"找不到這筆病患資料"
);
return;
}
request.setAttribute("patient", patient);
request.getRequestDispatcher("/patient-detail.jsp")
.forward(request, response);
}
}

這段程式沿用了 Day 19 建立的 Patient.java。

如果你之前的類別名稱、套件名稱或欄位不同,記得配合自己的專案調整。

四、看懂程式的關鍵部分

  1. 從網址取得病患編號

String idText = request.getParameter("id");

getParameter() 會取得請求中的參數值。

例如網址:

/patient/detail?id=1

就會取得字串 "1"。

但要注意,使用者輸入的資料不能直接當成整數使用,所以還需要轉型並檢查格式。

  1. 查詢資料庫

String sql =
"SELECT id, name, gender, birthday, phone "
+ "FROM patient WHERE id = ?";

再透過:

ps.setInt(1, id);

將病患編號傳入 SQL。

這樣可以避免直接拼接使用者輸入的內容,也讓查詢條件更容易維護。

  1. 將資料傳給 JSP

request.setAttribute("patient", patient);

這行會將查詢到的病患物件放進 request,讓 JSP 可以使用。

接著:

request.getRequestDispatcher("/patient-detail.jsp")
.forward(request, response);

就會將請求轉交給 JSP,顯示詳細資料。

五、建立 patient-detail.jsp

接著建立 patient-detail.jsp:

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

這裡使用 <c:out> 輸出欄位內容,可以減少直接輸出文字時的 HTML 注入風險。

記得確認專案已加入相容版本的 JSTL/Jakarta Tags 依賴。

六、如何從病患清單進入詳細頁面?

回到 Day 19 的病患清單 JSP,將病患編號改成連結:

使用者點選編號後,就會進入對應的詳細資料頁面。

例如:

http://localhost:8080/你的專案名稱/patient/detail?id=1

請將「你的專案名稱」換成自己的專案 Context Path。

如果找不到指定編號,Servlet 就會回傳 404 錯誤,而不是顯示一個空白的詳細資料頁面。

七、正式系統還需要注意什麼?

這次我們只練習基本的資料查詢和頁面呈現。

實際的醫療資訊系統還需要確認:

  • 使用者是否已登入。
  • 使用者是否有權限查看這筆資料。
  • 網頁是否只顯示工作所需的資訊。
  • 錯誤訊息是否避免暴露資料庫細節。
  • 是否有適當的操作紀錄與資料保護措施。

即使網址中的病患編號可以被修改,也不能因此讓使用者任意查看其他人的資料。每次查詢都必須在伺服器端檢查權限。

今日小結

今天我們完成了病患詳細資料頁面,學會:

  1. 使用 WHERE 查詢指定紀錄。
  2. 使用 Servlet 接收並驗證病患編號。
  3. 使用 JDBC 和 PreparedStatement 查詢資料。
  4. 使用 request.setAttribute() 傳遞物件。
  5. 使用 JSP 顯示詳細資料。
  6. 處理編號錯誤與資料不存在的情況。

Day 23 完成!

下一篇,我們要來處理另一個重要問題:使用者輸入的資料不一定正確,因此系統需要在儲存之前進行表單驗證。

參考資料:Jakarta Servlet 官方文件


上一篇
Day 22|幫醫療資訊小系統加入搜尋功能:使用 SQL 查詢指定病患
下一篇
Day 24|避免錯誤資料進入資料庫:建立表單驗證機制
系列文
30天從零打造醫療資訊小系統 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言