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

Java Servlet 伺服器端包含 (SSI) 技術實戰:模組化 Web 頁面構建

     編輯:Java 程式設計入門

前言:為什麼需要伺服器端包含?

在大型 Web 應用中,頁首 (Header)、頁尾 (Footer)、導航欄、側邊欄等片段在多個頁面重複出現。若在每個 JSP/HTML 重複編寫,維護成本極高。**伺服器端包含 (Server-Side Includes, SSI)** 允許在頁面中嵌入 Servlet 輸出,實現頁面片段的模組化復用。本文詳細講解 Java SSI 的語法、配置、實戰範例與現代替代方案。

一、SSI 核心語法與機制

1.1 檔案命名與啟用

  • 副檔名:**.shtml** (伺服器識別需解析 SSI 指令)。
  • Servlet 容器需啟用 SSI 支援 (Tomcat: conf/web.xml 取消註解 SSIServlet 映射 *.shtml)。

1.2 Servlet 標籤語法


<!--#servlet name="Servlet名稱" code="Servlet類別" codebase="類別路徑" 
      參數名1="參數值1" 參數名2="參數值2" ... -->
<!--#param name="參數名1" value="參數值1" -->
<!--#param name="參數名2" value="參數值2" -->
<!--#/servlet-->
  • name:在 web.xml 註冊的 Servlet 名稱。
  • code:Servlet 完整類別名 (可選,若已在 web.xml 映射)。
  • codebase:類別檔基礎路徑 (罕用)。
  • 參數可直接寫在 servlet 標籤屬性,或用獨立 param 標籤 (支援複雜值)。

二、完整實戰範例:Header + Footer 組合頁面

2.1 頁首 Servlet (Header.java)


import javax.servlet.*;
import java.io.*;

public class Header extends GenericServlet {
    public void service(ServletRequest req, ServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8"); // 建議 UTF-8
        PrintWriter out = resp.getWriter();

        // 取得傳入參數 title
        String title = "歡迎光臨"; // 預設值
        String[] titles = req.getParameterValues("title");
        if (titles != null && titles.length > 0) title = titles[0];

        // 輸出頁首 HTML 片段
        out.println("" + title + "");
        out.println("

*** " + title + " ***


"); out.flush(); // SSI 片段輸出建議 flush,不 close (由容器管理) } public String getServletInfo() { return "Header Fragment Servlet"; } public void init(ServletConfig cfg) throws ServletException { super.init(cfg); } public void destroy() { super.destroy(); } }

2.2 頁尾 Servlet (Footer.java)


public class Footer extends GenericServlet {
    public void service(ServletRequest req, ServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.println("
"); out.println("

版權所有 © 2024 某某科技有限公司

"); out.flush(); } // ... init/destroy/getServletInfo 同前 }

2.3 註冊部署描述檔


<servlet>
    <servlet-name>Header</servlet-name>
    <servlet-class>Header</servlet-class>
</servlet>
<servlet>
    <servlet-name>Footer</servlet-name>
    <servlet-class>Footer</servlet-class>
</servlet>

2.4 組合頁面


<!-- Together.shtml -->
<html>
<body>
<!--#servlet name="Header" title="首頁歡迎您" -->
<!--#/servlet-->

<div style="padding:20px;">
    <h2>主內容區域</h2>
    <p>這裡是頁面主體內容,可以是靜態 HTML 或動態生成。</p>
</div>

<!--#servlet name="Footer" -->
<!--#/servlet-->
</body>
</html>

三、SSI 進階特性與注意事項

3.1 巢狀包含

SSI 檔案中可再包含其他 SSI,但需容器支援 (Tomcat 預設支援)。避免循環包含導致無限遞歸。

3.2 傳遞請求參數


<!--#servlet name="UserPanel" userId="${param.userId}" -->

EL 表達式在 SSI 中**不一定支援**,建議在包含的 Servlet 中直接從 req.getParameter() 獲取原始請求參數 (SSI 包含時會傳遞原請求)。

3.3 效能考量

  • 每個 servlet 標籤觸發一次 service() 呼叫,過多片段會增加請求處理開銷。
  • 輸出使用 PrintWriter 直接寫入回應流,**避免大量字串拼接**。
  • 靜態片段 (如純 HTML 頁尾) 考慮直接用 <!--#include file="footer.html" --> (檔案包含),無 Servlet 開銷。

3.4 編碼一致性

所有參與 SSI 的 Servlet、.shtml 頁面、容器預設編碼**必須統一 (UTF-8)**,否則片段拼接會產生亂碼。

四、現代替代方案:為什麼 SSI 漸被取代?

五、總結與建議

  1. 維護舊系統:理解 SSI 語法、.shtml 映射、Servlet 片段輸出 (flush() 不 close())、編碼統一。
  2. 新專案:優先採用**模板引擎 (Thymeleaf 首選)** 或 **前端組件化**,SSI 角色已退居輔助/遷移過渡期。
  3. 核心思想不變:**「將重複頁面片段抽離為可復用模組」**,無論技術棧如何演進,模組化、關注點分離始終是軟體架構的基石。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案優勢適用場景
JSP 標籤檔 / 片段 (<jsp:include>, Tag File)原生 JSP 支援、EL/標籤庫整合、編譯期優化JSP 架構專案
模板引擎 (Thymeleaf, FreeMarker, Velocity)強大模板繼承、片段復用、邏輯分離、前端友好Spring MVC, 現代 Web 架構
前端組件化 (React, Vue, Web Components)瀏覽器端組合、獨立部署、狀態管理SPA, 微前端
Edge Side Includes (ESI)CDN/反向代理層組合、快取片段獨立失效高流量靜態化架構