JSP with Servlets (MVC Pattern)
See how a Servlet acts as a controller that handles logic and forwards to a JSP view, tying together everything covered in the course.
Introduction
Early in this course, JSP pages did everything themselves — reading parameters, running logic, and rendering HTML all in one file. That approach does not scale past a toy example. The Model-View-Controller (MVC) pattern is the standard fix in classic Java web development: a servlet handles logic as the controller, a JavaBean represents data as the model, and a JSP renders the view. This lesson builds a small but complete example tying every earlier lesson together.
- What Model, View, and Controller mean in a JSP application.
- How to write a controller servlet that processes a request.
- How the servlet forwards to a JSP view with data attached.
- Why this separation makes applications easier to maintain.
What Is MVC?
| Layer | Responsibility | Implemented As |
|---|---|---|
| Model | Holds and represents application data | A JavaBean, e.g. StudentBean |
| View | Renders the data as HTML for the browser | A JSP page using EL and JSTL |
| Controller | Reads input, runs logic, picks a view, forwards | A Java Servlet |
The request always enters through the controller first, never directly hitting the JSP. The controller decides what to do, prepares the model, and hands off rendering to the view — a clean separation of concerns.
The Model
The model is the same kind of JavaBean covered two lessons ago — a plain data carrier with no HTML and no request-handling logic.
// StudentBean.javapackage com.programinds.beans;
public class StudentBean { private String name; private String email; private int age;
public StudentBean() { }
public String getName() { return name; } public void setName(String name) { this.name = name; }
public String getEmail() { return email; } public void setEmail(String email) { this.email = email; }
public int getAge() { return age; } public void setAge(int age) { this.age = age; }}The Controller Servlet
The controller reads request parameters, validates them, builds the model, and forwards to the appropriate view — success or error — using RequestDispatcher, exactly as covered in the forwarding lesson.
// RegisterServlet.javapackage com.programinds.controllers;
import com.programinds.beans.StudentBean;import jakarta.servlet.*;import jakarta.servlet.http.*;import java.io.IOException;
public class RegisterServlet extends HttpServlet {
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name"); String email = request.getParameter("email"); String ageParam = request.getParameter("age");
if (name == null || name.trim().isEmpty() || email == null || !email.contains("@")) { request.setAttribute("errorMessage", "Please provide a valid name and email."); request.getRequestDispatcher("/register.jsp").forward(request, response); return; }
StudentBean student = new StudentBean(); student.setName(name); student.setEmail(email); student.setAge(ageParam != null && !ageParam.isEmpty() ? Integer.parseInt(ageParam) : 0);
request.setAttribute("student", student); request.getRequestDispatcher("/registration-success.jsp").forward(request, response); }}The View JSP
The view stays focused purely on presentation, reading the model through EL — no business logic, no scriptlets.
<!-- registration-success.jsp (View) --><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><html><body> <h2>Registration Successful</h2> <p>Name: ${student.name}</p> <p>Email: ${student.email}</p> <p>Age: ${student.age}</p></body></html><!-- register.jsp (Form + error display) --><c:if test="${not empty errorMessage}"> <p class="error">${errorMessage}</p></c:if><form action="register" method="post"> <input type="text" name="name" placeholder="Full name" /> <input type="email" name="email" placeholder="Email" /> <input type="number" name="age" placeholder="Age" /> <button type="submit">Register</button></form>Wiring It Together
The servlet is mapped to a URL, either with the @WebServlet annotation or in web.xml, so the browser posts to /register and the controller takes over from there.
@WebServlet("/register")public class RegisterServlet extends HttpServlet { // ...doPost as above}Why This Separation Matters
- The view (JSP) can be redesigned by a front-end developer without touching business logic.
- The controller (Servlet) can be unit tested independently of any HTML.
- The model (JavaBean) can be reused across multiple views — a web page, an API response, a report.
- Validation and data access logic live in exactly one place instead of being scattered across pages.
Common Mistakes
- Letting the JSP view read request parameters directly instead of relying on the model the controller prepared.
- Putting database calls inside the JSP — that logic belongs in the controller or a dedicated service class.
- Forwarding to the view before validating input, producing a broken or half-filled page.
- Skipping the controller entirely and letting the browser POST straight to a JSP, reintroducing scriptlet logic.
Best Practices
- Keep controllers thin — validate, delegate to a service layer, then forward.
- Keep views free of anything beyond EL and JSTL.
- Use one servlet per logical action, or a single front-controller servlet for larger applications.
- Name views and controllers consistently so the request flow is easy to trace.
Frequently Asked Questions
No, but it is the standard, maintainable pattern for anything beyond a trivial page, and is what you will find in almost every real-world JSP codebase.
Typically in the controller, or in a dedicated service class the controller calls, keeping the bean itself a simple data holder.
Yes, this is common — the servlet inspects the request and decides which JSP to forward to based on the outcome.
Key Takeaways
- MVC splits an application into Model (data), View (presentation), and Controller (logic).
- A servlet acts as controller, handling input and deciding what happens next.
- The servlet forwards to a JSP view, passing the model via request attributes.
- This separation keeps logic, data, and presentation independently maintainable.
Summary
MVC is the pattern that makes JSP applications maintainable at real-world scale, and it pulls together servlets, forwarding, JavaBeans, and JSTL views from every earlier lesson. Next, you will step back and review the common mistakes and best practices that separate fragile JSP code from solid, production-ready code.