Servlet 生命週期中 init() 僅執行一次,適合:
DataSource 並快取為實例變數,避免每請求查找。public class ControllerServlet extends HttpServlet {
private DataSource dataSource;
public void init(ServletConfig config) throws ServletException {
super.init(config);
try {
Context ctx = new InitialContext();
dataSource = (DataSource) ctx.lookup("jdbc/myDS"); // 單次查找
} catch (NamingException e) {
throw new ServletException("DataSource 查找失敗", e);
}
}
public DataSource getDataSource() { return dataSource; } // 供 doGet/doPost 復用
}
web.xml 或容器配置:reloadable="false" (Tomcat Context 屬性)。
| 策略 | 做法 | 效益 |
|---|---|---|
| 禁用預設 Session | JSP 頁面指令 <%@ page session="false" %> | 無 Session 需求的頁面 (靜態、登入頁) 節省記憶體與序列化開銷 |
| 避免存放大物件圖 | Session 僅存 ID、權限等輕量資料;大數據用快取 (Redis/Memcached) | 減少序列化成本、叢集同步流量、GC 壓力 |
| 及時失效 | session.invalidate() 登出時主動銷毀 | 釋放記憶體,防止 Session fixation 攻擊 |
| 降低逾時值 | web.xml <session-timeout>15</session-timeout> (分鐘) | 縮短無效 Session 佔用資源時間 |
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String encoding = req.getHeader("Accept-Encoding");
OutputStream out = resp.getOutputStream();
if (encoding != null && encoding.contains("gzip")) {
resp.setHeader("Content-Encoding", "gzip");
out = new GZIPOutputStream(out);
} else if (encoding != null && encoding.contains("deflate")) {
resp.setHeader("Content-Encoding", "deflate");
out = new DeflaterOutputStream(out);
}
// 寫入內容...
out.write(contentBytes);
out.flush();
}
效果: HTML/CSS/JS 文字內容壓縮率 70-90%,大幅降低頻寬與傳輸延遲。現代容器 (Tomcat 8+/Nginx) 可配置原生壓縮,無需代碼層面處理。
ThreadLocal、無狀態設計、同步區塊最小化、ConcurrentHashMap。Tomcat server.xml Executor 或 Connector 參數:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="200" minSpareThreads="25" maxIdleTime="60000" />
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" ... />
maxThreads:最大併發處理能力,依 CPU 核心數與 IO 密集度調整 (通常 200-500)。minSpareThreads:預熱執行緒,避免突發流量創建延遲。currentThreadsBusy 指標,動態調整。| 機制 | 語法 | 階段 | 效能 | 適用 |
|---|---|---|---|---|
| 靜態包含指令 | <%@ include file="x.jsp" %> | 編譯期 | 最快 (單 Servlet) | 極少變更片段 |
| 動態包含動作 | <jsp:include page="x.jsp" flush="true"/> | 請求期 | 稍慢 (獨立編譯/執行) | 頻繁變更、帶邏輯片段 |
原則: 能用靜態包含絕不用動態包含。
<jsp:useBean id="cache" class="com.example.DataCache" scope="application" />
page (預設):請求結束即銷毀,適合臨時計算物件。request:轉發鏈路共享,適合請求級資料傳遞。session:用戶會話共享,適合購物車、用戶偏好。application:全域單例,適合配置、快取、服務定位器。誤用後果: 請求級物件放 session → 記憶體洩漏;全域快取放 page → 重複創建、失效。
reloadable="false"init() 快取session="false"SingleThreadModel 實作maxThreads 按壓測調整include 指令,動態片段用 include 動作useBean scope 精準匹配生命週期Servlet/JSP 效能優化無銀彈,唯有「全鏈路精細管理」:初始化快取、執行緒池化、Session 瘦身、傳輸壓縮、包含機制正確選擇、作用域精準控制。八大技法涵蓋生命週期全階段,配合壓測驗證與監控告警,可將系統吞吐量提升 3-10 倍。現代架構中,這些原理同樣適用於 Spring Boot、Vert.x、Netty 等框架的調優實踐。