Building a Small MVC Web App
Harry
· 11 Sep 2026
· 10 views
Building a Small MVC Web App
Let us tie everything together by building a small MVC web application - a book catalog with list, view, and search functionality. This demonstrates how servlets, JSP, JSTL, and sessions work together.
The Model Layer
Start with a simple POJO and a service class:
public class Book {
private Long id;
private String title;
private String author;
private double price;
// constructor, getters, setters
}
public class BookService {
private static final List<Book> BOOKS = List.of(
new Book(1L, "Clean Code", "Robert Martin", 29.99),
new Book(2L, "Effective Java", "Joshua Bloch", 34.99),
new Book(3L, "Design Patterns", "Gang of Four", 39.99)
);
public List<Book> findAll() { return BOOKS; }
public Book findById(long id) {
return BOOKS.stream().filter(b -> b.getId() == id).findFirst().orElse(null);
}
public List<Book> search(String q) {
return BOOKS.stream()
.filter(b -> b.getTitle().toLowerCase().contains(q.toLowerCase()))
.toList();
}
}
The Controller Layer
A single servlet routes requests based on the URL path:
@WebServlet("/books/*")
public class BookController extends HttpServlet {
private final BookService bookService = new BookService();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String path = req.getPathInfo();
if (path == null || "/".equals(path)) {
req.setAttribute("books", bookService.findAll());
req.getRequestDispatcher("/WEB-INF/views/book-list.jsp")
.forward(req, resp);
} else {
long id = Long.parseLong(path.substring(1));
req.setAttribute("book", bookService.findById(id));
req.getRequestDispatcher("/WEB-INF/views/book-detail.jsp")
.forward(req, resp);
}
}
}
The View Layer
JSP files use JSTL to render the data:
<%@ taglib uri="jakarta.tags.core" prefix="c" %>
<%@ taglib uri="jakarta.tags.fmt" prefix="fmt" %>
<%@ include file="/WEB-INF/fragments/header.jsp" %>
<h1>Book Catalog</h1>
<c:forEach items="${books}" var="book">
<div class="book-card">
<h2><a href="books/${book.id}">${book.title}</a></h2>
<p>by ${book.author}</p>
<p><fmt:formatNumber value="${book.price}" type="currency"/></p>
</div>
</c:forEach>
<%@ include file="/WEB-INF/fragments/footer.jsp" %>
Project Structure
src/main/java/com/example/
model/Book.java
service/BookService.java
controller/BookController.java
src/main/webapp/
WEB-INF/
web.xml
views/
book-list.jsp
book-detail.jsp
fragments/
header.jsp
footer.jsp
This structure scales. As the application grows, add more servlets for different resources, more JSP views, and a real database in the model layer.
Key Points
- MVC separates the application into Model (data), Controller (logic), and View (presentation).
- Servlets act as controllers that process requests and forward to JSP views.
- JSP with JSTL handles presentation without scriptlets.
- Place JSP files under
WEB-INF/to prevent direct browser access. - This pattern is the foundation of Spring MVC and other Java web frameworks.