1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/webapp
├── /views
│ ├── layouts
│ └── layout.jsp
├── ├── pages
│ ├── home.jsp
│ └── home_content.jsp
└── /assets
├── css/
├── bootstrap.min.css
└── style.css
├── js/
├── bootstrap.bundle.min.js
└── main.js
└── img/
Download Bootstrap from https://getbootstrap.com.
1
2
bootstrap.min.css → ./assets/css/
bootstrap.bundle.min.js → ./assets/js/
1
2
3
<link rel="stylesheet" href="${pageContext.request.contextPath}/assets/css/bootstrap.min.css">
<script src="${pageContext.request.contextPath}/assets/js/bootstrap.bundle.min.js"></script>
A single, reusable layout that pulls in Bootstrap and renders a body section.
./webapp/views/layout.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>${param.pageTitle}</title>
<link href="${pageContext.request.contextPath}/assets/css/bootstrap.css" rel="stylesheet">
<link rel="stylesheet" href="${pageContext.request.contextPath}/assets/css/style.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="${pageContext.request.contextPath}/views/home.jsp">
JSP Shop
</a>
</div>
</nav>
<main class="container py-4">
<jsp:include page="/views/pages/${contentPage}" />
</main>
<footer class="bg-light border-top mt-5">
<div class="container py-3 text-center small text-muted">
© 2025 Hieu Nguyen - AI lecturer - FPT University Can Tho
</div>
</footer>
<script src="${pageContext.request.contextPath}/assets/js/bootstrap.bundle.min.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/main.js"></script>
</body>
</html>
home.jsp stays minimal: it only passes title and body into layout.jsp. The actual content lives in partials homeBody.jsp.
1
2
3
4
5
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:include page="/views/layout/layout.jsp" >
<jsp:param name="pageTitle" value="Home - JSP Shop" />
<jsp:param name="bodyPage" value="home_content.jsp" />
</jsp:include>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card shadow-sm">
<div class="card-body">
<h1 class="h3 mb-3">Welcome to JSP Shop</h1>
<p class="mb-0">
This is a simple Home page.
We’re using a shared
<code>
views/layout.jsp
</code>
for consistent UI with Bootstrap.
</p>
</div>
</div>
</div>
</div>
Place your files under ./webapp/assets/…. They will be publicly available at:
1
2
3
http://localhost:8080/<context>/assets/css/style.css
http://localhost:8080/<context>/assets/js/main.js
http://localhost:8080/<context>/assets/images/logo.png
Examples:
1
2
body { min-height: 100vh; }
.navbar-brand { font-weight: 700; letter-spacing: .3px; }
1
console.log("Assets loaded (Model 1 + Bootstrap).");
Tip: Always prefix asset URLs in JSP with
${pageContext.request.contextPath}
to work under any context path.
To publish resources then web.xml:
1
2
3
4
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/assets/*</url-pattern>
</servlet-mapping>
— Refers to the Default Servlet provided by the servlet container (Tomcat, Jetty, etc.), which is responsible for serving static resources.
— This tells the servlet container to serve all requests starting with /assets/ directly from the file system under src/main/webapp/assets.
1
2
3
4
...
<welcome-file-list>
<welcome-file>views/home.jsp</welcome-file>
</welcome-file-list>
http://localhost:8080/<your-context>/
Source demo: jsp-shop-05