首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 留言板教學(八):發文頁面開發——JSTL 版

     編輯:Java 相關知識

本篇實作發布主題貼文頁面,包含表單驗證、登入攔截、錯誤回顯、CSRF 防護,採用 JSTL + EL 保持視圖純淨。

頁面流程

  1. 用戶點擊「發文」連結,進入 postForm。
  2. 攔截器/Filter 檢查 Session 是否有 loginUser,未登入導向登入頁並保存 redirectUrl。
  3. 頁面顯示發文表單(標題必填、內容必填)。
  4. 提交至 postSubmit,Service 驗證後持久化,重導向列表頁。

JSTL 發文頁完整代碼

JSTL 發文頁面截圖

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<html><head><title>發布主題</title>
<style>.error{color:red} textarea{width:100%;height:150px} .csrf{display:none}</style></head><body>
<h2>發布新主題</h2>

<form action="postSubmit" method="post">
  <!-- CSRF Token -->
  <input type="hidden" name="csrfToken" value="<c:out value='${sessionScope.csrfToken}'/>" class="csrf"/>
  <input type="hidden" name="userId" value="<c:out value='${sessionScope.loginUser.id}'/>" />
  
  <div>
    <label>標題(必填):</label>
    <input type="text" name="title" size="80" maxlength="200" 
           value="<c:out value='${param.title}'/>" required/>
    <span class="error"><c:out value="${errors.title}" /></span>
  </div>
  <div>
    <label>內容(必填):</label><br/>
    <textarea name="content" required><c:out value="${param.content}"/></textarea>
    <span class="error"><c:out value="${errors.content}" /></span>
  </div>
  <div>
    <input type="submit" value="發布" />
    <input type="button" value="取消" onclick="history.back()" />
  </div>
</form>
</body></html>

關鍵技術點

  • HTML5 原生驗證:required、maxlength 瀏覽器端首輪攔截,減少無效請求。
  • 用戶輸入回顯:${param.title}、${param.content},驗證失敗時保留輸入。
  • 錯誤訊息顯示:Controller 驗證失敗放入 errors Map,頁面 ${errors.title} 顯示。
  • CSRF Token:Session 產生隨機 Token,表單隱藏域攜帶,Filter 驗證防跨站偽造請求。
  • 登入用戶 ID 隱藏域:${sessionScope.loginUser.id} 直接取得,Controller 無需額外傳遞。
  • XSS 防護:所有動態輸出 <c:out> 自動轉義。

Controller 驗證與 CSRF 邏輯片段

@PostMapping("postSubmit")
public String postSubmit(HttpServletRequest request, 
                         @RequestParam String title, @RequestParam String content) {
    // 1. CSRF 驗證
    String sessionToken = (String) request.getSession().getAttribute("csrfToken");
    String formToken = request.getParameter("csrfToken");
    if (sessionToken == null || !sessionToken.equals(formToken)) {
        return "error/csrf"; // 或拋異常
    }
    // 2. 業務驗證
    Map<String, String> errors = new HashMap<>();
    if (title == null || title.trim().isEmpty()) errors.put("title", "標題不能為空");
    if (title != null && title.length() > 200) errors.put("title", "標題不可超過 200 字");
    if (content == null || content.trim().isEmpty()) errors.put("content", "內容不能為空");
    if (!errors.isEmpty()) {
        request.setAttribute("errors", errors);
        return "postForm"; // 轉發回表單,保留 param 與 errors
    }
    // 3. 業務處理
    User loginUser = (User) request.getSession().getAttribute("loginUser");
    messageService.postTopic(loginUser.getId(), title.trim(), content.trim());
    // 4. 重導向防重複提交
    return "redirect:list";
}

下一篇將展示同功能的 Scriptlet 版本對比。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved