LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1719 min read

Including Files (jsp:include)

Learn the difference between the runtime jsp:include action and the compile-time include directive, and build a shared header and footer.

Introduction

Almost every multi-page site shares common pieces — a header with navigation, a footer with a copyright line. Duplicating that markup in every JSP file is a maintenance nightmare. JSP gives you two different mechanisms for pulling in another file's content, and they behave very differently under the hood: the include directive and the jsp:include action.

What You Will Learn
  • How the compile-time include directive works.
  • How the runtime jsp:include action works.
  • When to choose one over the other.
  • How to build a shared header and footer for a real page.

The include Directive

The include directive, <%@ include file="..." %>, is resolved at translation time — before the page is even compiled into a servlet. The included file's text is copied and pasted directly into the including page's source, then the combined result is compiled as one servlet.

Using the include Directive
<%@ include file="header.jsp" %>
<h1>Dashboard</h1>
<p>Welcome to your dashboard.</p>
<%@ include file="footer.jsp" %>
Think "Copy-Paste at Compile Time"

Because the directive merges source code before compilation, the included file shares the same request-time variables and scriptlet context as the parent page — it behaves as if you had typed its contents directly into your file.

The jsp:include Action

jsp:include is a standard action, resolved at request time (runtime), not compile time. Each request, the container calls the included page as its own separate servlet, captures its output, and merges that output into the response.

Using the jsp:include Action
<jsp:include page="header.jsp" />
<h1>Dashboard</h1>
<p>Welcome to your dashboard.</p>
<jsp:include page="footer.jsp" />

Directive vs Action

Aspectinclude Directivejsp:include Action
Resolved atTranslation/compile timeRequest/runtime
Included contentMerged as raw source before compilingCalled and output captured each request
PerformanceSlightly faster (no repeated calls)Slightly slower (a call every request)
FlexibilityStatic — the file path cannot be dynamicDynamic — page path can be an EL expression
Best forContent that never changes, like a fixed footerContent that varies, or reused compiled fragments

A typical layout keeps header.jsp and footer.jsp in a shared folder and includes them from every page in the app.

/common/header.jsp
<!-- /common/header.jsp -->
<header>
<h1>PrograMinds Store</h1>
<nav>
<a href="/home.jsp">Home</a>
<a href="/products.jsp">Products</a>
<a href="/cart.jsp">Cart</a>
</nav>
</header>
/common/footer.jsp
<!-- /common/footer.jsp -->
<footer>
<p>&copy; 2026 PrograMinds. All rights reserved.</p>
</footer>
products.jsp Using the Shared Fragments
<!-- products.jsp -->
<jsp:include page="/common/header.jsp" />
<main>
<h2>Our Products</h2>
<p>Browse our full catalog below.</p>
</main>
<jsp:include page="/common/footer.jsp" />

Passing Parameters

jsp:include can pass extra parameters to the included page using nested jsp:param tags, useful for telling a shared header which nav link should be highlighted.

<jsp:include page="/common/header.jsp">
<jsp:param name="activePage" value="products" />
</jsp:include>
<!-- inside header.jsp, reading the param -->
<a href="/products.jsp" class="${param.activePage == 'products' ? 'active' : ''}">Products</a>

Common Mistakes

Avoid These Mistakes
  • Using the include directive with a dynamic, per-request file path — it cannot vary, since it is resolved before the page ever runs.
  • Expecting jsp:param values inside an include directive — jsp:param only works with the jsp:include action.
  • Forgetting that heavy use of jsp:include adds a small runtime cost on every request compared to the directive.
  • Mixing incompatible HTML structure between includes, like opening a <div> in the header and never closing it, which breaks every page that includes it.

Best Practices

  • Use the include directive for genuinely static, unchanging fragments like a copyright footer.
  • Use jsp:include when the fragment needs parameters or independent request-time logic.
  • Keep shared fragments in a dedicated folder like /common/ or /WEB-INF/includes/.
  • Test that included fragments render correctly in isolation as well as inside a parent page.

Frequently Asked Questions

Yes, the page attribute can point to any resource the container can dispatch to, including a servlet mapped by URL.

No, jsp:param is only recognized inside the jsp:include action, not the compile-time directive.

jsp:include is generally the safer default for real applications since it supports parameters and dynamic paths.

Key Takeaways

  • The include directive merges source code at compile time, before the servlet exists.
  • jsp:include calls another page at request time and merges its output.
  • jsp:include supports dynamic paths and jsp:param; the directive does not.
  • Shared headers and footers keep multi-page JSP sites consistent and maintainable.

Summary

Includes solve reuse within a single response. The next lesson tackles a related but different problem: handing off an entire request to another resource entirely, using jsp:forward.

Next Lesson →

Forwarding Requests (jsp:forward)