需求:註冊頁面包含多個 Checkbox(如興趣標籤)與年/月/日三個下拉選單,點擊提交時將勾選項目與生日組合為字串送往 Servlet。以下提供前端組裝、後端解析的完整範例。
<%@ page contentType="text/html;charset=UTF-8" %>
<form id="regForm" action="RegisterServlet" method="post">
<div>
<label>用戶名:<input type="text" name="username" required></label>
</div>
<div>
<label>密碼:<input type="password" name="password" required></label>
</div>
<fieldset>
<legend>興趣標籤(多選)</legend>
<label><input type="checkbox" name="hobby" value="reading"> 閱讀</label>
<label><input type="checkbox" name="hobby" value="music"> 音樂</label>
<label><input type="checkbox" name="hobby" value="sport"> 運動</label>
<label><input type="checkbox" name="hobby" value="travel"> 旅遊</label>
</fieldset>
<fieldset>
<legend>生日</legend>
<select name="birthYear" id="birthYear">
<option value="">年</option>
</select>
<select name="birthMonth" id="birthMonth">
<option value="">月</option>
</select>
<select name="birthDay" id="birthDay">
<option value="">日</option>
</select>
</fieldset>
<button type="submit">註冊</button>
</form>
<script>
// 動態生成年份選項 (1900 ~ 當前年份)
const yearSel = document.getElementById('birthYear');
for (let y = new Date().getFullYear(); y >= 1900; --y) {
yearSel.add(new Option(y, y));
}
// 月份
const monthSel = document.getElementById('birthMonth');
for (let m = 1; m <= 12; ++m) {
monthSel.add(new Option(m < 10 ? '0'+m : m, m));
}
// 日期(簡易版,實際應依年月動態調整)
const daySel = document.getElementById('birthDay');
for (let d = 1; d <= 31; ++d) {
daySel.add(new Option(d < 10 ? '0'+d : d, d));
}
// 提交前可選:將 checkbox 陣列合併為單一字串(後端也可直接用 getParameterValues)
document.getElementById('regForm').addEventListener('submit', function(e) {
const hobbies = Array.from(document.querySelectorAll('input[name="hobby"]:checked'))
.map(cb => cb.value).join(',');
// 若後端偏好單一欄位,可塞入隱藏域
// const hidden = document.createElement('input');
// hidden.type = 'hidden'; hidden.name = 'hobbiesStr'; hidden.value = hobbies;
// this.appendChild(hidden);
});
</script>
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
// 1. 普通欄位
String username = req.getParameter("username");
String password = req.getParameter("password");
// 2. Checkbox 陣列(同 name 多值)
String[] hobbyArr = req.getParameterValues("hobby"); // 可能為 null
String hobbiesStr = (hobbyArr != null) ? String.join(",", hobbyArr) : "";
// 3. 生日三欄位組合
String year = req.getParameter("birthYear");
String month = req.getParameter("birthMonth");
String day = req.getParameter("birthDay");
String birthDate = (year != null && month != null && day != null)
? String.format("%s-%s-%s", year, month, day) : "";
System.out.printf("用戶: %s, 興趣: %s, 生日: %s%n", username, hobbiesStr, birthDate);
// 4. 業務邏輯:存入資料庫、驗證等...
// userService.register(username, password, hobbiesStr, birthDate);
resp.sendRedirect("registerSuccess.jsp");
}
}
<input type="hidden" name="hobbiesCombined" id="hobbiesCombined">
<input type="hidden" name="birthDateCombined" id="birthDateCombined">
<script>
document.getElementById('regForm').addEventListener('submit', function() {
const hobbies = Array.from(document.querySelectorAll('input[name="hobby"]:checked'))
.map(cb => cb.value).join('|');
document.getElementById('hobbiesCombined').value = hobbies;
const y = document.getElementById('birthYear').value;
const m = document.getElementById('birthMonth').value;
const d = document.getElementById('birthDay').value;
document.getElementById('birthDateCombined').value = [y,m,d].join('-');
});
</script>
後端直接 req.getParameter("hobbiesCombined")、req.getParameter("birthDateCombined") 即可,無需自行組裝。
| 環節 | 關鍵 API / 技巧 |
|---|---|
| Checkbox 多值 | request.getParameterValues("name") 返回 String[] |
| 下拉選單 | request.getParameter("name") 取單值 |
| 字串組合 | 前端 Array.join(',') 或後端 String.join(",", arr) |
| 編碼 | req.setCharacterEncoding("UTF-8") 必須在 getParameter 前呼叫 |
| 驗證 | 後端必須再次驗證必填、格式、長度,防止繞過前端檢查 |
採用「前端負責蒐集組裝、後端負責解析驗證」的分工,即可乾淨實現 Checkbox 與下拉選單資料的組合傳遞。