許多開發者誤以為 JSP 性能遠遜於 Servlet。事實上,首次訪問編譯耗時較長,後續請求直接執行編譯後的 Servlet .class 文件,性能幾乎無差異。Web 容器處理 JSP 請求分四階段:
容器會檢查 JSP 文件時間戳,若未修改則直接復用已編譯的 Servlet。
<%@ page language="java" contentType="text/html;charset=gb2312"
import="java.text.*,java.util.*;" %>
<html>
<head><title>Show time</title></head>
<body>
Hello :
<%
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
String str = format.format(new Date());
%>
<%=str %>
</body></html>
package org.apache.jsp.ch04;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.text.*;
import java.util.*;
public final class showdate_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static java.util.List _jspx_dependants;
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
JspFactory _jspxFactory = JspFactory.getDefaultFactory();
PageContext pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true);
ServletContext application = pageContext.getServletContext();
ServletConfig config = pageContext.getServletConfig();
HttpSession session = pageContext.getSession();
JspWriter out = pageContext.getOut();
Object page = this;
try {
response.setContentType("text/html;charset=gb2312");
// 靜態 HTML → out.write()
out.write("\r\n<html>\r\n<head>\r\n<title>Show time</title>\r\n</head>\r\n<body> \r\n\tHello : \r\n\t");
// JSP 腳本片段 → 直接保留為局部變量聲明
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
String str = format.format(new Date());
// 表達式 <%=str%> → out.print(str)
out.print(str);
out.write("\r\n</body>\r\n</html>");
} catch (Throwable t) {
// 異常處理與頁面錯誤轉發
} finally {
_jspxFactory.releasePageContext(pageContext);
}
}
}
| JSP 元素 | Servlet 對應 | 說明 |
|---|---|---|
頁面指令 <%@page ...%> | response.setContentType() | 設置響應頭屬性 |
| HTML 靜態模板 | out.write("...") | 逐行輸出靜態內容 |
腳本片段 <% ... %> | _jspService 方法體局部變量/語句 | 直接嵌入 Servlet 方法中 |
表達式 <= ... %> | out.print(...) | 輸出變量值到響應流 |
聲明 <%! ... %> | 類成員變量/方法 | 轉為 Servlet 類成員 |
public void _jspInit() { } // 初始化,僅執行一次
public void _jspDestroy() { } // 銷毀,僅執行一次
public void _jspService(...) { } // 處理每次請求,核心邏輯在此
<%@ page buffer="16kb" autoFlush="true" %>development="false" 禁用文件修改檢查理解 JSP 到 Servlet 的轉譯機制,不僅能幫助排查運行時錯誤 (如行號對應),更能指導編寫高性能、可維護的視圖層代碼。現代項目建議採用前後端分離架構,JSP 逐步退出歷史舞台。