問題現象
- JSP 頁面放在
WebRoot/view/ 目錄。
- 表單
<form action="loginSubmit"> 提交後報 404,實際請求路徑缺少 /view 前綴。
原因分析
- 相對路徑
action="loginSubmit" 相對於**當前請求 URL**,而非文件系統路徑。
- 若當前頁面為
https://host/app/view/login.jsp,相對路徑解析為 https://host/app/view/loginSubmit;但 Servlet 映射可能在 /app/loginSubmit。
解決方案:動態構建絕對路徑
方案一:JSP 內聯腳本 (傳統)
<%
String ctx = request.getContextPath(); // 如 /myapp
String basePath = request.getScheme() + "://" +
request.getServerName() + ":" +
request.getServerPort() + ctx + "/";
%>
<form action="<%=basePath%>loginSubmit" method="post">
...
</form>
方案二:JSTL core 標簽 (推薦)
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<c:set var="basePath" value="${pageContext.request.contextPath}/" />
<form action="${basePath}loginSubmit" method="post"> ... </form>
方案三:HTML 標籤 (全局生效)
<head>
<base href="<%=request.getRequestURL().toString().replace(request.getRequestURI(), request.getContextPath()+"/")%>" />
</head>
<!-- 所有相對鏈接、表單 action 自動基於 base href 解析 -->
Servlet 映射對應
@WebServlet("/loginSubmit") // 或 web.xml /loginSubmit
public class LoginServlet extends HttpServlet { ... }
- 映射路徑
/loginSubmit 為**相對於 Context Path** 的絕對路徑。
- 表單 action 必須包含 Context Path:
${pageContext.request.contextPath}/loginSubmit。
調試技巧
- 瀏覽器開發者工具 Network 面板查看實際請求 URL。
- 在 JSP 輸出
${pageContext.request.contextPath} 確認上下文路徑。
- 檢查
web.xml 或註解中 url-pattern 是否以 / 開頭。