What are Servlets?
Think of a servlet like a restaurant waiter:
- 🍽️ Customer (Browser) makes a request: "I want spaghetti"
- 📝 Waiter (Servlet) takes the order, sends it to the kitchen
- 🍝 Kitchen prepares the food (business logic)
- ✅ Waiter brings the food back to customer (HTTP response)
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?
@WebServlet("/hello")- Maps URL /hello to this servletextends HttpServlet- Inherit servlet functionalitydoGet()- Handle GET requests (browser visits URL)HttpServletRequest- Data from client (parameters, headers)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