JSP 是把 Java 程式碼寫進 HTML 的伺服器端網頁技術:使用者打開網頁時,伺服器先執行 Java,再把算好的 HTML 送到瀏覽器。它在 2000 年代是 Java 網站的標準做法,今天仍撐著大量企業、政府與金融系統的畫面層。這篇文章從「JSP 是什麼」開始,說明它的運作原理、四種基本標籤、EL 與 JSTL 的現代寫法、表單與資料庫範例,最後誠實回答一個常見問題:現在還值得學 JSP 嗎?本文屬於《網頁程式語言》系列,前後端技術的全貌請先看〈網頁程式設計入門〉。
一、JSP 是什麼?
JSP(Java Server Pages,現正式名稱為 Jakarta Server Pages)是一種伺服器端網頁技術,讓開發者把 Java 程式碼嵌入 HTML,由伺服器執行後產生動態網頁。檔案副檔名是 .jsp,必須放在支援 Java 的網頁容器(例如 Apache Tomcat)上執行,瀏覽器收到的永遠是處理完的 HTML,看不到任何 Java 原始碼。
JSP 由昇陽(Sun Microsystems)在 1999 年推出,目的是簡化 Servlet 的寫法:Servlet 要用 Java 一行一行 println 拼出 HTML,JSP 則反過來,以 HTML 為主、在需要動態內容的地方插入 Java。2017 年底 Oracle 宣布把 Java EE 移交 Eclipse 基金會,之後改名 Jakarta EE,JSP 也跟著改稱 Jakarta Server Pages;從 Jakarta EE 9 起,程式套件從 javax.servlet.jsp 改為 jakarta.servlet.jsp,這是升級舊專案到 Tomcat 10 以後最常踩到的第一個坑。
二、JSP 怎麼運作?從 .jsp 到 HTML 的四個步驟
JSP 頁面第一次被請求時,容器會把它翻譯成 Servlet 原始碼、編譯成 class,之後每次請求都直接執行這個 class。理解這四步,就能解釋為什麼 JSP 第一次開啟特別慢、以及為什麼修改 .jsp 檔通常不用重啟伺服器。

- 翻譯(Translation):容器內的 JSP 引擎(Tomcat 稱為 Jasper)讀取 .jsp,把 HTML 轉成輸出敘述、把 Java 片段原樣保留,產生一個 Servlet 的 .java 檔。
- 編譯(Compilation):把 .java 編譯成 .class。這兩步只在第一次請求或檔案修改後發生,所以第一位訪客會等比較久。
- 執行(Execution):容器載入 class,呼叫它的服務方法,Java 程式讀取請求參數、查資料庫、組合資料。
- 回應(Response):把組合完成的 HTML 透過 HTTP 回傳給瀏覽器。瀏覽器只看到 HTML,不知道背後是 JSP。
整個流程都發生在網頁伺服器與應用程式伺服器這一端;很多 JSP 部署會用 Apache 或 Nginx 在前面接收請求、把動態頁面轉交 Tomcat 處理,這種分工在〈應用程式伺服器是什麼〉有更完整的說明。
三、JSP 基本語法:四種標籤與指令
JSP 的核心語法只有四種標籤,都以 <% 開頭、%> 結尾,差別在第二個字元。以下範例都能直接放進 Tomcat 的 webapps 目錄執行。
1. 表達式標籤 <%= %>:把值印到網頁上
表達式標籤會把 Java 表達式的結果轉成字串,直接輸出在 HTML 的那個位置,不需要寫分號。
<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html lang="zh-Hant">
<body>
<h2>Hello, JSP!</h2>
現在的時間是:<%= new java.util.Date() %>
</body>
</html>
這段程式每次重新整理都會顯示伺服器當下的日期與時間。第一行的 page 指令宣告輸出編碼是 UTF-8,少了它,中文很容易變成問號。
2. Scriptlet 標籤 <% %>:寫邏輯,不直接輸出
Scriptlet 裡面是一般的 Java 敘述,用來宣告變數、做運算、寫判斷,本身不會輸出任何東西,要顯示結果得搭配表達式標籤或 out.println()。
<%
String name = "王小明";
int age = 25;
%>
姓名:<%= name %><br>
年齡:<%= age %>
畫面會顯示「姓名:王小明」與「年齡:25」。Scriptlet 是最早期、也最容易讓程式碼失控的寫法,第六節會說明現代專案為什麼盡量不用它。
3. 宣告標籤 <%! %>:定義方法與成員變數
宣告標籤裡的內容會變成翻譯後 Servlet 類別的成員,可以在同一頁的其他地方呼叫。
<%!
public String greetUser(String userName) {
return "Hello, " + userName + "!";
}
%>
<h2>歡迎訊息:</h2>
<p><%= greetUser("Alice") %></p>
4. 註解與指令
JSP 註解 <%-- --%> 只留在伺服器,不會出現在送給瀏覽器的 HTML 裡;一般的 HTML 註解 <!-- --> 則會被原樣送出,任何人按右鍵檢視原始碼都看得到。指令標籤 <%@ %> 用來設定整頁的屬性,最常用的有三個:
<%-- 這行註解不會送到瀏覽器 --%> <%@ page contentType="text/html; charset=UTF-8" import="java.util.List" %> <%@ include file="header.jsp" %> <%@ taglib prefix="c" uri="jakarta.tags.core" %>
page:設定編碼、要匯入的 Java 套件、錯誤頁面等。include:把另一個檔案在翻譯階段合併進來,常用於共用的頁首、頁尾。taglib:載入標籤庫,第六節的 JSTL 就靠它。Jakarta Standard Tag Library 3.0(Jakarta EE 10)起 uri 改為jakarta.tags.core;舊專案的http://java.sun.com/jsp/jstl/core規格上仍可使用,但搭配的 JSTL 函式庫必須換成 Jakarta 版,否則同樣會卡在javax與jakarta的命名空間差異。
四、條件判斷與迴圈
在 Scriptlet 裡可以使用所有標準的 Java 流程控制語法。下面兩段分別示範 if/else 與 for 迴圈,注意 Java 敘述結尾要有分號,這和 HTML 交錯時很容易漏掉。
<%
int age = 20;
if (age >= 18) {
out.println("您已成年");
} else {
out.println("您尚未成年");
}
%>
<%
for (int i = 1; i <= 5; i++) {
out.println("這是第 " + i + " 次迴圈<br>");
}
%>
第一段依年齡輸出不同文字,第二段輸出 1 到 5。out 是 JSP 內建的輸出物件,不用自己宣告;同類的內建物件還有 request、response、session、application,下一節會用到。
五、表單處理與資料庫連線
接收表單靠 request.getParameter(),連資料庫靠 JDBC。先看表單:
<form method="post" action="welcome.jsp">
姓名:<input type="text" name="name"><br>
<input type="submit" value="送出">
</form>
<%
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
if (name != null && !name.isBlank()) {
out.println("歡迎," + name + "!");
}
%>
送出表單後,同一頁會顯示「歡迎,+您輸入的名字」。setCharacterEncoding 那行是處理中文表單的關鍵,漏掉就會出現亂碼。接著是讀取 MySQL 資料表的範例:
<%@ page import="java.sql.*" %>
<%
String url = "jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=UTF-8";
try (Connection conn = DriverManager.getConnection(url, "dbuser", "dbpassword");
PreparedStatement ps = conn.prepareStatement("SELECT id, name FROM users WHERE status = ?")) {
ps.setInt(1, 1);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
out.println("ID:" + rs.getInt("id") + ",名字:" + rs.getString("name") + "<br>");
}
}
} catch (SQLException e) {
out.println("資料庫連線失敗,請稍後再試。");
}
%>
PreparedStatement 帶參數,不要把使用者輸入直接串進 SQL 字串,這是 OWASP 列為第一優先的 SQL 注入防護;第二,帳號密碼與連線字串不該寫在 .jsp 裡,應放在容器的 DataSource 設定並使用連線池;第三,資料庫邏輯根本不該出現在畫面層,這正是下一節要談的事。範例用 try-with-resources 自動關閉連線,比舊教材裡一長串 finally 手動關閉安全許多。
六、現代寫法:EL 與 JSTL 取代 Scriptlet
2000 年代中期以後的 JSP 專案,普遍避免在頁面裡寫 Scriptlet,改用 EL(Expression Language)取值、JSTL(Standard Tag Library)寫流程。原因很實際:Java 與 HTML 混在同一個檔案裡,設計師不敢動、工程師難測試,一個 500 行的 .jsp 沒有人敢維護。

正確的分工是 MVC:Servlet(或 Spring MVC 的 Controller)負責接收請求、呼叫商業邏輯、把結果放進 request 屬性,然後轉交 JSP;JSP 只負責把資料排成畫面。前面第五節的資料庫範例,改成 MVC 寫法後畫面層會變成這樣:
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<h2>會員清單</h2>
<c:if test="${empty users}">
<p>目前沒有資料。</p>
</c:if>
<ul>
<c:forEach var="u" items="${users}">
<li>ID:${u.id},名字:<c:out value="${u.name}"/></li>
</c:forEach>
</ul>
- EL
${...}:讀取 request、session 等範圍裡的物件與屬性,${u.name}會自動呼叫getName(),完全不用寫 Java。 - JSTL
<c:if>、<c:forEach>:用標籤取代 if 與 for,讀起來和 HTML 一致。 <c:out>:輸出時自動把<、>等字元轉義,是防止跨站腳本(XSS)最省力的方法;直接用${u.name}輸出使用者填入的內容則沒有這層保護。
如果您接手的舊專案滿是 Scriptlet,不必一次重寫,可以先把新功能用 EL 與 JSTL 寫,舊頁面在修改時順手轉換。
七、JSP 與 PHP、ASP.NET 差在哪?
三者都是「伺服器端產生 HTML」的技術,差別在語言、執行環境與生態。只列對決策最有影響的三點,各技術的完整介紹請看各自專文:
- 語言與型別:JSP 背後是 Java,強型別、需要編譯;PHP 是直譯式、弱型別,改完存檔就能看結果;ASP.NET 以 C# 為主,同樣是編譯式強型別。
- 主機門檻:PHP 幾乎所有虛擬主機都內建;JSP 需要 Tomcat 等 Java 容器,記憶體需求較高,多半要租 VPS 或雲端主機;ASP.NET Core 可跑 Linux,但舊版 ASP.NET 綁 Windows。
- 典型應用:JSP 常見於銀行、政府、ERP 等大型 Java 系統;PHP 主宰中小企業官網、WordPress 與電商套件;ASP.NET 多見於微軟生態的企業內部系統。
整體前後端技術怎麼搭、哪種專案該選哪種語言,〈網頁程式設計入門〉有系統性的整理,本文不重複。
八、JSP 現在的定位:還值得學嗎?
JSP 沒有死,但已經退到「維護既有系統」的位置;新專案很少以 JSP 當畫面層。三個事實可以說明它現在的處境:
- 規格仍在更新:Jakarta Server Pages 隨 Jakarta EE 持續發版,Tomcat 10.1 與 11 都內建支援,所以既有系統升級容器不成問題,只要處理
javax改jakarta的命名空間。 - 主流框架不再優先支援:Spring Boot 官方文件明列 JSP 的限制,例如打包成可執行 jar 時 JSP 無法使用,因此 Spring 生態普遍改用 Thymeleaf 等範本引擎。
- 架構潮流轉向前後端分離:新系統多由 Java 只提供 REST API,畫面交給 React、Vue 等前端框架,伺服器端已經不產生 HTML。
所以答案分兩種人:如果您在台灣的金融、政府、製造業資訊部門工作,或要接手維護既有 Java 系統,JSP 與 JSTL 仍是必備能力,而且這類系統的壽命通常以十年計;如果您是想從零開始學網頁開發的新手,把 Java 學好、再學 Spring Boot 與前端框架,JSP 只需要看得懂即可。
九、網站主的視角:JSP 網站的主機與維護
對非工程背景的網站主來說,JSP 網站最大的差別不在語法,而在主機與人力。我們替企業評估舊網站改版時,遇到 JSP 站點會先看四件事:
- 主機類型:台灣主流虛擬主機以 PHP 與 MySQL 為主,很少提供 Tomcat。JSP 站通常跑在自有伺服器、VPS 或雲端主機上,月費與管理成本都高於共享主機,搬家前要先確認新環境能跑 Java。
- Java 版本:很多舊站停在 Java 8 與 Tomcat 7、8,升級到 Java 17 或 21 時,除了命名空間,還要處理停用的 API 與第三方套件相容性,這是報價落差最大的一項。
- 誰能維護:會 Java 的工程師不少,但願意維護 Scriptlet 滿天飛的舊 JSP 專案的人不多。交接時務必拿到完整原始碼、建置方式與資料庫結構文件。
- SEO 體質:JSP 本身對搜尋引擎沒有壞處,伺服器端輸出的 HTML 反而利於索引;常見問題是網址帶
;jsessionid=參數造成重複內容,以及缺少壓縮與快取設定,這些屬於技術 SEO的範圍,與語言無關。

本站(newscan.com.tw)以 PHP 建置,原因正是第一點:對以官網與詢問單為目標的中小企業,PHP 主機的普及度與成本優勢很明確。但這不代表 JSP 站該改寫,運作正常、能找到人維護的系統,重寫的風險往往高於維持。
十、結論
JSP 是把 Java 嵌進 HTML、由伺服器產生動態網頁的技術,語法核心只有四種標籤,真正的難點在架構:把邏輯留在 Servlet、畫面交給 EL 與 JSTL。它在新專案裡的地位已被前後端分離與其他範本引擎取代,但在企業既有系統中仍會存在很久。
學習順序建議:先把 HTML 與 JavaScript 基礎打穩,再學 Java 與 Servlet,最後才碰 JSP 與 JSTL;順序反過來,會不知道 JSP 到底在替誰省工。
十一、常見問答 FAQ
JSP 是什麼?
JSP 和 Java、Servlet 差在哪?
JSP 現在還有人用嗎?還值得學嗎?
JSP 和 PHP 哪個好?
.jsp 檔案要怎麼開啟或執行?
參考來源
- Jakarta EE Working Group,〈Jakarta Server Pages〉,Eclipse Foundation 官方規格。
- Apache Software Foundation,〈Jasper 2 JSP Engine How To〉,Apache Tomcat 官方文件。
- Spring,〈Spring Boot Reference:JSP Limitations〉,Spring 官方文件。
- Oracle,〈The Java EE Tutorial:JavaServer Pages Technology〉,Oracle 官方文件。
- OWASP,〈SQL Injection Prevention Cheat Sheet〉,OWASP Cheat Sheet Series。
- Eclipse Foundation,〈Jakarta EE 8: Past, Present, and Future〉,Eclipse Newsletter,2019。
- Jakarta EE Working Group,〈Jakarta Standard Tag Library 3.0〉,Eclipse Foundation 官方規格,2022。
- 新視野網頁設計,〈網頁程式設計:打造專業網站的必學技術與技巧〉,本站自有內容。
文中 Jakarta EE、Tomcat 與 Spring Boot 的支援狀態依 2026 年 9 月查閱的官方文件整理;第九節為本站承接網站改版評估時的實務檢查項目,不涉及特定客戶資料。