1.

JSP include (jsp:include / @include) 完全ガイド

編集
この記事の要点
  • JSP / Struts1 には2 種類の include: <%@ include %> 静的 と <jsp:include> 動的
  • 静的 include (@include): コンパイル時に本文に展開、変数共有可、Servlet が 1 つに統合
  • 動的 include (jsp:include): 実行時にレスポンスを取り込み、変数別、<jsp:param> でパラメータ渡し可
  • JSTL <c:import> は外部 URL も取り込め、より汎用
  • モダンな代替: Thymeleafth:insert / th:replace / th:fragment

JSP の include 概要

JSP / Servlet 系の Web アプリでヘッダ / フッタ / サイドバーなど共通部品を別 JSP に切り出して取り込む仕組みです。Struts 1.x / 2.x、素の JSP、JSF いずれでも使われてきました。

取り込み方は大きく分けて 静的 (コンパイル時)動的 (実行時) の 2 種類があり、用途と挙動が異なります。

静的 include: <%@ include file="..." %>

<%-- common/header.jsp --%>
<%
String pageTitle = "Welcome";
int year = 2026;
%>
<!DOCTYPE html>
<html><head><title><%= pageTitle %></title></head><body>
<header>Site Header</header>

<%-- 親 JSP --%>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ include file="common/header.jsp" %>

<h1>Main Content</h1>
<p>Year: <%= year %></p>   <%-- header.jsp の変数を使える --%>

<%@ include file="common/footer.jsp" %>

特徴:

  • コンパイル時に親 JSP の本文にそのまま展開される
  • 変数 / メソッド / インポートを共有
  • 1 つの Servlet にコンパイルされるので高速
  • include 先を編集しても親が再コンパイルされない (古い内容のまま) ことがある → クリーンビルド必要

動的 include: <jsp:include page="..." />

<%-- 親 JSP --%>
<%@ page contentType="text/html; charset=UTF-8" %>
<html><body>
<jsp:include page="common/header.jsp">
    <jsp:param name="pageTitle" value="Welcome" />
    <jsp:param name="year" value="2026" />
</jsp:include>

<h1>Main Content</h1>

<jsp:include page="common/footer.jsp" />
</body></html>

<%-- common/header.jsp --%>
<%
String pageTitle = request.getParameter("pageTitle");
String year      = request.getParameter("year");
%>
<header>[<%= year %>] <%= pageTitle %></header>

特徴:

  • 実行時に取り込み先 JSP を実行し、出力結果 (HTML) だけを取り込む
  • 取り込み先は独立した Servlet なので変数共有不可
  • <jsp:param> でパラメータ渡し
  • 動的に取込先を切替可能 (page="${url}")
  • 静的 include より若干オーバーヘッドあり

2 種類の使い分け早見表

項目静的 @include動的 jsp:include
処理タイミングコンパイル時リクエスト時
変数共有★ できるできない
パラメータ渡し不可★ jsp:param で可
取込ファイル動的指定不可 (リテラル必須)★ ${url} で可
性能★ 速い少し遅い
再コンパイル取込先変更時に親も要独立して反映
主用途共通宣言 / 定数ヘッダ / フッタ / ウィジェット

JSTL <c:import>

JSTL の <c:import> はさらに高機能で、外部 URL も取り込めます:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%-- 内部 JSP を取り込み --%>
<c:import url="/common/header.jsp">
    <c:param name="pageTitle" value="Welcome" />
</c:import>

<%-- 外部 URL を取り込み (RSS, REST) --%>
<c:import url="https://api.example.com/feed.xml" var="feed" />
${feed}

<%-- 文字コード指定 --%>
<c:import url="/common/header.jsp" charEncoding="UTF-8" />

<%-- 取り込み内容を変数に --%>
<c:import url="/common/sidebar.jsp" var="sidebarHtml" />
<aside>${sidebarHtml}</aside>

Apache Tiles (現在 EOL)

Struts 1 系で「テンプレートエンジン」として広く使われた Apache Tiles も include を抽象化していました。共通レイアウトと「穴埋めパーツ」を分離できますが、2017 年に Apache が End of Life を宣言。新規採用は非推奨です:

<!-- tiles-defs.xml -->
<tiles-definitions>
    <definition name="layout" template="/WEB-INF/layout/main.jsp">
        <put-attribute name="title"  value="Default Title"/>
        <put-attribute name="header" value="/WEB-INF/parts/header.jsp"/>
        <put-attribute name="body"   value=""/>
        <put-attribute name="footer" value="/WEB-INF/parts/footer.jsp"/>
    </definition>

    <definition name="user.list" extends="layout">
        <put-attribute name="title" value="User List"/>
        <put-attribute name="body"  value="/WEB-INF/jsp/user/list.jsp"/>
    </definition>
</tiles-definitions>

Sitemesh

Sitemesh は「逆テンプレート」方式: 子ページが title / body を持ち、Sitemesh が後付けでレイアウトを合成。Tiles より導入が軽く、シンプルなプロジェクトでよく使われました:

<!-- WEB-INF/decorators.xml -->
<decorators defaultdir="/decorators">
    <decorator name="main" page="main.jsp">
        <pattern>/*</pattern>
    </decorator>
</decorators>

<!-- decorators/main.jsp -->
<html>
<head><title><decorator:title default="Default" /></title></head>
<body>
    <header>Site Header</header>
    <main><decorator:body /></main>
    <footer>Site Footer</footer>
</body>
</html>

モダン代替: Thymeleaf

Spring Boot 等で現在主流のテンプレートエンジンが Thymeleaf。include 相当は th:insert / th:replace / th:fragment:

<!-- templates/fragments/header.html -->
<header th:fragment="siteHeader (pageTitle)">
    <h1 th:text="${pageTitle}">Default</h1>
</header>

<!-- 利用側 -->
<div th:insert="~{fragments/header :: siteHeader('Welcome')}"></div>
<!-- div の内側に挿入 -->

<div th:replace="~{fragments/header :: siteHeader('Welcome')}"></div>
<!-- div ごと置換 -->
属性動作
th:fragment再利用ブロックを宣言
th:insert呼び出し側タグの内側に挿入
th:replace呼び出し側タグごと置換 (推奨)
th:includefragment の中身だけ挿入 (Thymeleaf 3 で非推奨)

FAQ

Q: 静的と動的、どちらを使うべき?
A: 動的 (jsp:include) が無難。変数共有が必要な定数だけ静的に。

Q: 取り込み先の変更が反映されない
A: 静的 include で起きがちな問題。work/Catalina 配下の生成 Servlet を削除 → 再起動。

Q: include したいファイルが WEB-INF 下にある
A: 直接 URL アクセスできなくとも JSP 内 jsp:include page="/WEB-INF/parts/header.jsp" で取り込めます。Tomcat はこれを許可。

Q: 新規プロジェクトでも JSP include を使うべき?
A: 新規なら Spring Boot + Thymeleaf 推奨。JSP は古いプロジェクト保守用と割り切る方が良い。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. include
  2. taglib

最近更新/作成されたページ