Servlets & JSP

Building Web Applications with Jakarta EE

← Back to Index

What are Servlets?

Think of a servlet like a restaurant waiter:

A Servlet is a Java class that handles HTTP requests and generates HTTP responses. It's the foundation of web applications in Jakarta EE.

Servlet = Server + Applet (small application that runs on the server)

How Servlets Work

Browser sends request → Web Server (Tomcat/Payara) → Servlet Container
                                                                    ↓
                                                          Servlet processes request
                                                                    ↓
                                                          Generates HTML response
                                                                    ↓
Browser displays page ← Web Server ← Response sent back

Creating Your First Servlet

Simple Servlet Example

package com.example;

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
import java.io.*;

@WebServlet("/hello")  // URL mapping: /hello
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request,
                             HttpServletResponse response)
            throws ServletException, IOException {

        // Set response content type
        response.setContentType("text/html");

        // Get output writer
        PrintWriter out = response.getWriter();

        // Generate HTML response
        out.println("<html>");
        out.println("<head><title>Hello Servlet</title></head>");
        out.println("<body>");
        out.println("<h1>Hello from Servlet!</h1>");
        out.println("<p>Current time: " + new java.util.Date() + "</p>");
        out.println("</body></html>");
    }
}

Access it: http://localhost:8080/myapp/hello

What's Happening?

  1. @WebServlet("/hello") - Maps URL /hello to this servlet
  2. extends HttpServlet - Inherit servlet functionality
  3. doGet() - Handle GET requests (browser visits URL)
  4. HttpServletRequest - Data from client (parameters, headers)
  5. HttpServletResponse - Data to send back (HTML, JSON, etc.)

HTTP Methods: doGet vs doPost

doGet() - Reading Data

@WebServlet("/users")
public class UserServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request,
                             HttpServletResponse response)
            throws ServletException, IOException {

        // Get query parameter: /users?id=123
        String userId = request.getParameter("id");

        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        out.println("<h1>User ID: " + userId + "</h1>");
    }
}

doPost() - Submitting Data

@WebServlet("/register")
public class RegisterServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request,
                              HttpServletResponse response)
            throws ServletException, IOException {

        // Get form data
        String username = request.getParameter("username");
        String email = request.getParameter("email");
        String password = request.getParameter("password");

        // Process registration (save to database)
        // ...

        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<h1>Registration Successful!</h1>");
        out.println("<p>Welcome, " + username + "!</p>");
    }
}

HTML Form for POST

<form action="/myapp/register" method="POST">
    <input type="text" name="username" placeholder="Username">
    <input type="email" name="email" placeholder="Email">
    <input type="password" name="password" placeholder="Password">
    <button type="submit">Register</button>
</form>
Method Purpose Data in URL Use Case
GET Retrieve data Yes (visible) View pages, search, read
POST Submit data No (in body) Forms, login, create data
PUT Update data No (in body) Update existing records
DELETE Delete data Optional Remove records

Servlet Lifecycle

@WebServlet("/lifecycle")
public class LifecycleServlet extends HttpServlet {

    // 1. Called ONCE when servlet is first created
    @Override
    public void init() throws ServletException {
        System.out.println("Servlet initialized!");
        // Load config, connect to database, etc.
    }

    // 2. Called for EVERY request
    @Override
    protected void doGet(HttpServletRequest request,
                             HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("Handling request...");
        response.getWriter().println("Hello!");
    }

    // 3. Called ONCE when servlet is destroyed (server shutdown)
    @Override
    public void destroy() {
        System.out.println("Servlet destroyed!");
        // Close connections, cleanup resources
    }
}

Lifecycle Flow:

Server starts → init() called → Servlet ready
                                          ↓
            Request 1 → service() → doGet()/doPost()
            Request 2 → service() → doGet()/doPost()
            Request 3 → service() → doGet()/doPost()
                      ... many requests ...
                                          ↓
Server stops → destroy() called → Servlet removed

What is JSP (JavaServer Pages)?

Problem with Servlets: Writing HTML with out.println() is painful!

// Servlet - HTML in Java (hard to maintain!)
out.println("<html>");
out.println("<body>");
out.println("<h1>Hello " + name + "</h1>");
out.println("</body></html>");

Solution: JSP - Java in HTML (easy to maintain!)

JSP (JavaServer Pages) allows you to embed Java code directly in HTML files. Behind the scenes, JSP files are converted to servlets by the server.

Simple JSP Example (hello.jsp)

<!DOCTYPE html>
<html>
<head>
    <title>Hello JSP</title>
</head>
<body>
    <h1>Hello from JSP!</h1>

    <!-- Embed Java code with <% %> -->
    <p>Current time: <%= new java.util.Date() %></p>

    <%
        // Java code block
        String name = "Alice";
        int age = 25;
    %>

    <p>Name: <%= name %></p>
    <p>Age: <%= age %></p>

    <%
        // Conditional logic
        if (age >= 18) {
    %>
        <p>You are an adult!</p>
    <% } else { %>
        <p>You are a minor!</p>
    <% } %>

</body>
</html>

Access it: http://localhost:8080/myapp/hello.jsp

JSP Syntax Elements

1. Scriptlets <% ... %> - Java Code

<%
    int x = 10;
    int y = 20;
    int sum = x + y;
%>

2. Expressions <%= ... %> - Print Value

<p>Sum: <%= sum %></p>
<p>Random: <%= Math.random() %></p>

3. Declarations <%! ... %> - Class-level Variables/Methods

<%!
    // This becomes a class member
    private int counter = 0;

    public String greet(String name) {
        return "Hello, " + name + "!";
    }
%>

<p>Counter: <%= ++counter %></p>
<p><%= greet("Bob") %></p>

4. Directives <%@ ... %> - Page Configuration

<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*, java.text.*" %>
<%@ include file="header.jsp" %>

5. Comments

<!-- HTML comment (visible in source) -->
<%-- JSP comment (not sent to browser) --%>

Servlet + JSP Working Together

Best Practice: Servlet handles logic, JSP handles presentation

Servlet (Controller)

@WebServlet("/user-profile")
public class UserProfileServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request,
                             HttpServletResponse response)
            throws ServletException, IOException {

        // 1. Get data from database
        String userId = request.getParameter("id");
        User user = database.findUserById(userId);

        // 2. Put data in request scope
        request.setAttribute("user", user);

        // 3. Forward to JSP for display
        request.getRequestDispatcher("/WEB-INF/profile.jsp")
               .forward(request, response);
    }
}

JSP (View) - profile.jsp

<!DOCTYPE html>
<html>
<head>
    <title>User Profile</title>
</head>
<body>
    <%
        // Get data from request
        User user = (User) request.getAttribute("user");
    %>

    <h1>Profile: <%= user.getName() %></h1>
    <p>Email: <%= user.getEmail() %></p>
    <p>Age: <%= user.getAge() %></p>
</body>
</html>

Flow:

Browser → /user-profile?id=123 → UserProfileServlet
                                           ↓
                                  1. Fetch user from DB
                                  2. Store in request
                                  3. Forward to JSP
                                           ↓
                                      profile.jsp
                                           ↓
                                  Display HTML to browser

JSP Standard Tag Library (JSTL)

Problem: Java code in JSP is still messy!

Solution: JSTL provides clean tags instead of Java code

Without JSTL (ugly)

<%
    List<String> items = (List<String>) request.getAttribute("items");
    for (String item : items) {
%>
    <li><%= item %></li>
<% } %>

With JSTL (clean)

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

<c:forEach var="item" items="${items}">
    <li>${item}</li>
</c:forEach>

Common JSTL Tags

<!-- Variables -->
<c:set var="name" value="Alice" />
<p>${name}</p>

<!-- Conditionals -->
<c:if test="${user.age >= 18}">
    <p>Adult</p>
</c:if>

<c:choose>
    <c:when test="${score >= 90}">Grade: A</c:when>
    <c:when test="${score >= 80}">Grade: B</c:when>
    <c:otherwise>Grade: C</c:otherwise>
</c:choose>

<!-- Loops -->
<c:forEach var="user" items="${users}">
    <p>${user.name}</p>
</c:forEach>

<!-- URL building -->
<c:url value="/user-profile" var="profileUrl">
    <c:param name="id" value="123" />
</c:url>
<a href="${profileUrl}">View Profile</a>

Session Management

Storing User Data Across Requests

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request,
                              HttpServletResponse response)
            throws ServletException, IOException {

        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // Validate credentials
        if (authenticate(username, password)) {
            // Get or create session
            HttpSession session = request.getSession();

            // Store user in session
            session.setAttribute("username", username);
            session.setAttribute("loggedIn", true);

            response.sendRedirect("dashboard.jsp");
        } else {
            response.sendRedirect("login.jsp?error=invalid");
        }
    }
}

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request,
                             HttpServletResponse response)
            throws ServletException, IOException {

        // Invalidate session
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate();
        }

        response.sendRedirect("login.jsp");
    }
}

Accessing Session in JSP

<!-- dashboard.jsp -->
<%
    String username = (String) session.getAttribute("username");
    Boolean loggedIn = (Boolean) session.getAttribute("loggedIn");

    if (loggedIn == null || !loggedIn) {
        response.sendRedirect("login.jsp");
        return;
    }
%>

<h1>Welcome, <%= username %>!</h1>
<a href="logout">Logout</a>

Best Practices

✅ DO:

  • Use MVC pattern - Servlet (Controller) + JSP (View)
  • Put JSP in WEB-INF - Prevents direct access, must go through servlet
  • Use JSTL and EL - Avoid Java code in JSP
  • Validate input - Check all user input for security
  • Use POST for forms - Especially for sensitive data
  • Manage sessions properly - Set timeouts, invalidate on logout
  • Use forward() for internal - Stays on server, efficient
  • Use sendRedirect() for external - Goes to client, new request

❌ DON'T:

  • Don't put business logic in JSP - Keep it in servlets/services
  • Don't use scriptlets - Use JSTL and EL instead
  • Don't store sensitive data in session - Minimize stored data
  • Don't forget to close resources - Use try-with-resources
  • Don't ignore XSS attacks - Escape user input
  • Don't use GET for sensitive operations - Use POST instead

Summary

  • Servlets are Java classes that handle HTTP requests/responses
  • @WebServlet annotation maps URLs to servlets
  • doGet() handles GET requests, doPost() handles POST requests
  • Lifecycle: init() → service() (doGet/doPost) → destroy()
  • JSP embeds Java code in HTML for easier view creation
  • JSP Syntax: <% code %>, <%= expression %>, <%! declaration %>
  • JSTL provides clean tags to avoid Java code in JSP
  • MVC Pattern: Servlet handles logic, JSP displays results
  • Sessions maintain user state across multiple requests
  • Modern alternative: Use JAX-RS for REST APIs instead of servlets