JavaServer Pages JSP Development
JavaServer Pages (JSP)
JavaServer Pages (JSP) is a server-side Java technology that enables the creation of dynamic web content by embedding Java code in HTML pages. JSP provides a simplified way to create dynamic web applications while separating presentation logic from business logic.
Table of Contents
- JSP Fundamentals
- JSP Syntax
- Directives
- Scriptlets and Expressions
- Expression Language (EL)
- JSTL (JSP Standard Tag Library)
- Custom Tags
- JSP Lifecycle
- Best Practices
JSP Fundamentals
What is JSP?
JSP is a technology that allows you to embed Java code directly into HTML pages, which are then compiled into servlets by the web container. Key benefits include:
- Separation of presentation and business logic
- Simplified web page development
- Automatic servlet generation
- Built-in support for session management
- Integration with Java beans and custom tags
Basic JSP Structure
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My JSP Page</title>
</head>
<body>
<h1>Welcome to JSP!</h1>
<p>Current time: <%= new java.util.Date() %></p>
<%
String userName = "Guest";
if (request.getParameter("name") != null) {
userName = request.getParameter("name");
}
%>
<p>Hello, <%= userName %>!</p>
</body>
</html>
JSP Syntax
Comments
<%-- JSP Comment - not visible in HTML source --%>
<!-- HTML Comment - visible in HTML source -->
<%--
Multi-line JSP comment
This will not appear in the generated HTML
--%>
Declaration Tags
<%!
// Declaration tag - defines variables and methods at class level
private int pageViewCount = 0;
public String getCurrentTime() {
return new java.util.Date().toString();
}
public int incrementCounter() {
return ++pageViewCount;
}
%>
<html>
<body>
<h2>Page Statistics</h2>
<p>Page views: <%= incrementCounter() %></p>
<p>Current time: <%= getCurrentTime() %></p>
</body>
</html>
Expression Tags
<%@ page import="java.util.*" %>
<html>
<body>
<h2>Expression Examples</h2>
<!-- Simple expressions -->
<p>Current date: <%= new Date() %></p>
<p>Random number: <%= Math.random() %></p>
<p>Server info: <%= application.getServerInfo() %></p>
<!-- Request parameters -->
<p>User name: <%= request.getParameter("username") %></p>
<p>User agent: <%= request.getHeader("User-Agent") %></p>
<!-- Session attributes -->
<p>Session ID: <%= session.getId() %></p>
<p>Session creation time: <%= new Date(session.getCreationTime()) %></p>
</body>
</html>
Directives
Page Directive
<%@ page
language="java"
contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
import="java.util.*, java.text.*"
session="true"
buffer="8kb"
autoFlush="true"
isThreadSafe="true"
errorPage="error.jsp"
isErrorPage="false"
%>
<!DOCTYPE html>
<html>
<head>
<title>Page Directive Example</title>
</head>
<body>
<%
// Using imported classes
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
List<String> items = new ArrayList<>();
items.add("Item 1");
items.add("Item 2");
items.add("Item 3");
%>
<h2>Formatted Date: <%= sdf.format(new Date()) %></h2>
<ul>
<% for (String item : items) { %>
<li><%= item %></li>
<% } %>
</ul>
</body>
</html>
Include Directive
<!-- header.jsp -->
<%@ page contentType="text/html; charset=UTF-8" %>
<header>
<nav>
<ul>
<li><a href="home.jsp">Home</a></li>
<li><a href="about.jsp">About</a></li>
<li><a href="contact.jsp">Contact</a></li>
</ul>
</nav>
</header>
<!-- main.jsp -->
<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
<style>
nav ul { list-style-type: none; }
nav li { display: inline; margin-right: 10px; }
</style>
</head>
<body>
<%@ include file="header.jsp" %>
<main>
<h1>Welcome to My Website</h1>
<p>This is the main content area.</p>
</main>
<%@ include file="footer.jsp" %>
</body>
</html>
<!-- footer.jsp -->
<footer>
<p>© 2024 My Website. All rights reserved.</p>
</footer>
Taglib Directive
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<title>JSTL Example</title>
</head>
<body>
<c:set var="greeting" value="Hello, World!" />
<h1><c:out value="${greeting}" /></h1>
<c:if test="${not empty param.username}">
<p>Welcome, <c:out value="${param.username}" />!</p>
</c:if>
</body>
</html>
Scriptlets and Expressions
Scriptlets for Complex Logic
<%@ page import="java.util.*, java.sql.*" %>
<!DOCTYPE html>
<html>
<body>
<h2>User Management</h2>
<%
String action = request.getParameter("action");
String message = "";
if ("login".equals(action)) {
String username = request.getParameter("username");
String password = request.getParameter("password");
// Simple authentication logic
if ("admin".equals(username) && "password".equals(password)) {
session.setAttribute("user", username);
session.setAttribute("role", "admin");
message = "Login successful!";
} else {
message = "Invalid credentials!";
}
} else if ("logout".equals(action)) {
session.invalidate();
message = "Logged out successfully!";
}
String currentUser = (String) session.getAttribute("user");
String userRole = (String) session.getAttribute("role");
%>
<% if (message.length() > 0) { %>
<div class="message"><%= message %></div>
<% } %>
<% if (currentUser != null) { %>
<p>Welcome, <%= currentUser %>! (Role: <%= userRole %>)</p>
<a href="?action=logout">Logout</a>
<% if ("admin".equals(userRole)) { %>
<h3>Admin Panel</h3>
<ul>
<li><a href="manage-users.jsp">Manage Users</a></li>
<li><a href="system-settings.jsp">System Settings</a></li>
</ul>
<% } %>
<% } else { %>
<form method="post" action="?action=login">
<label>Username: <input type="text" name="username" required></label><br>
<label>Password: <input type="password" name="password" required></label><br>
<input type="submit" value="Login">
</form>
<% } %>
</body>
</html>
Data Processing Example
<%@ page import="java.util.*, java.text.*" %>
<!DOCTYPE html>
<html>
<body>
<h2>Sales Report</h2>
<%
// Sample sales data
Map<String, Double> salesData = new HashMap<>();
salesData.put("January", 15000.0);
salesData.put("February", 18500.0);
salesData.put("March", 22000.0);
salesData.put("April", 19500.0);
salesData.put("May", 25000.0);
double totalSales = 0;
for (Double amount : salesData.values()) {
totalSales += amount;
}
DecimalFormat df = new DecimalFormat("#,##0.00");
%>
<table border="1">
<tr>
<th>Month</th>
<th>Sales Amount</th>
<th>Percentage</th>
</tr>
<%
for (Map.Entry<String, Double> entry : salesData.entrySet()) {
String month = entry.getKey();
Double amount = entry.getValue();
double percentage = (amount / totalSales) * 100;
%>
<tr>
<td><%= month %></td>
<td>$<%= df.format(amount) %></td>
<td><%= String.format("%.1f", percentage) %>%</td>
</tr>
<% } %>
<tr style="font-weight: bold;">
<td>Total</td>
<td>$<%= df.format(totalSales) %></td>
<td>100.0%</td>
</tr>
</table>
</body>
</html>
Expression Language (EL)
Basic EL Syntax
<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html>
<body>
<h2>Expression Language Examples</h2>
<!-- Implicit objects -->
<p>Request parameter 'name': ${param.name}</p>
<p>Session ID: ${pageContext.session.id}</p>
<p>Context path: ${pageContext.request.contextPath}</p>
<!-- Arithmetic operations -->
<p>10 + 5 = ${10 + 5}</p>
<p>20 * 3 = ${20 * 3}</p>
<p>100 / 4 = ${100 / 4}</p>
<p>17 % 5 = ${17 % 5}</p>
<!-- String operations -->
<p>String length: ${fn:length("Hello World")}</p>
<p>Uppercase: ${fn:toUpperCase("hello")}</p>
<p>Contains: ${fn:contains("Hello World", "World")}</p>
<!-- Conditional operations -->
<p>Is admin: ${sessionScope.role eq 'admin' ? 'Yes' : 'No'}</p>
<p>Has parameters: ${not empty param ? 'Yes' : 'No'}</p>
</body>
</html>
EL with Collections
<%@ page import="java.util.*" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
// Setup test data
List<Map<String, Object>> employees = new ArrayList<>();
Map<String, Object> emp1 = new HashMap<>();
emp1.put("id", 1);
emp1.put("name", "John Doe");
emp1.put("department", "IT");
emp1.put("salary", 75000);
employees.add(emp1);
Map<String, Object> emp2 = new HashMap<>();
emp2.put("id", 2);
emp2.put("name", "Jane Smith");
emp2.put("department", "HR");
emp2.put("salary", 65000);
employees.add(emp2);
Map<String, Object> emp3 = new HashMap<>();
emp3.put("id", 3);
emp3.put("name", "Bob Johnson");
emp3.put("department", "IT");
emp3.put("salary", 80000);
employees.add(emp3);
request.setAttribute("employees", employees);
%>
<!DOCTYPE html>
<html>
<body>
<h2>Employee List</h2>
<table border="1">
<tr>
<th>ID</th>
<th>Name</th>
<th>Department</th>
<th>Salary</th>
</tr>
<c:forEach var="employee" items="${employees}">
<tr>
<td>${employee.id}</td>
<td>${employee.name}</td>
<td>${employee.department}</td>
<td>$${employee.salary}</td>
</tr>
</c:forEach>
</table>
<h3>Statistics</h3>
<p>Total employees: ${fn:length(employees)}</p>
<!-- Filter IT employees -->
<h3>IT Department</h3>
<ul>
<c:forEach var="employee" items="${employees}">
<c:if test="${employee.department eq 'IT'}">
<li>${employee.name} - $${employee.salary}</li>
</c:if>
</c:forEach>
</ul>
</body>
</html>
JSTL (JSP Standard Tag Library)
Core Tags
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<body>
<h2>JSTL Core Tags</h2>
<!-- Variable manipulation -->
<c:set var="userName" value="John Doe" />
<c:set var="userAge" value="30" />
<p>User: <c:out value="${userName}" /></p>
<p>Age: <c:out value="${userAge}" /></p>
<!-- Conditional logic -->
<c:if test="${userAge >= 18}">
<p style="color: green;">User is an adult.</p>
</c:if>
<c:choose>
<c:when test="${userAge < 13}">
<p>Child</p>
</c:when>
<c:when test="${userAge < 20}">
<p>Teenager</p>
</c:when>
<c:when test="${userAge < 65}">
<p>Adult</p>
</c:when>
<c:otherwise>
<p>Senior</p>
</c:otherwise>
</c:choose>
<!-- Iteration -->
<c:set var="fruits" value="apple,banana,cherry,date" />
<h3>Fruits:</h3>
<ul>
<c:forTokens var="fruit" items="${fruits}" delims=",">
<li><c:out value="${fruit}" /></li>
</c:forTokens>
</ul>
<!-- URL manipulation -->
<c:url var="profileUrl" value="/profile">
<c:param name="userId" value="123" />
<c:param name="tab" value="settings" />
</c:url>
<p><a href="${profileUrl}">View Profile</a></p>
<!-- Error handling -->
<c:catch var="exception">
<c:set var="result" value="${10 / 0}" />
</c:catch>
<c:if test="${not empty exception}">
<p style="color: red;">Error: ${exception.message}</p>
</c:if>
</body>
</html>
Formatting Tags
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="now" value="<%= new java.util.Date() %>" />
<c:set var="price" value="1234.56" />
<c:set var="percentage" value="0.75" />
<!DOCTYPE html>
<html>
<body>
<h2>JSTL Formatting Examples</h2>
<!-- Date formatting -->
<h3>Date Formatting</h3>
<p>Default: <fmt:formatDate value="${now}" /></p>
<p>Short date: <fmt:formatDate value="${now}" type="date" dateStyle="short" /></p>
<p>Medium date: <fmt:formatDate value="${now}" type="date" dateStyle="medium" /></p>
<p>Long date: <fmt:formatDate value="${now}" type="date" dateStyle="long" /></p>
<p>Full date: <fmt:formatDate value="${now}" type="date" dateStyle="full" /></p>
<p>Time: <fmt:formatDate value="${now}" type="time" /></p>
<p>Both: <fmt:formatDate value="${now}" type="both" /></p>
<p>Custom: <fmt:formatDate value="${now}" pattern="yyyy-MM-dd HH:mm:ss" /></p>
<!-- Number formatting -->
<h3>Number Formatting</h3>
<p>Default: <fmt:formatNumber value="${price}" /></p>
<p>Currency: <fmt:formatNumber value="${price}" type="currency" /></p>
<p>Percentage: <fmt:formatNumber value="${percentage}" type="percent" /></p>
<p>Pattern: <fmt:formatNumber value="${price}" pattern="###,##0.00" /></p>
<!-- Internationalization -->
<fmt:setLocale value="en_US" />
<p>US Currency: <fmt:formatNumber value="${price}" type="currency" /></p>
<fmt:setLocale value="de_DE" />
<p>German Currency: <fmt:formatNumber value="${price}" type="currency" /></p>
<!-- Bundles -->
<fmt:setBundle basename="messages" />
<p><fmt:message key="welcome.message" /></p>
<fmt:message key="user.greeting">
<fmt:param value="John" />
</fmt:message>
</body>
</html>
Function Tags
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="text" value="Hello World from JSP" />
<c:set var="email" value="[email protected]" />
<!DOCTYPE html>
<html>
<body>
<h2>JSTL Function Examples</h2>
<!-- String functions -->
<h3>String Functions</h3>
<p>Original: ${text}</p>
<p>Length: ${fn:length(text)}</p>
<p>Uppercase: ${fn:toUpperCase(text)}</p>
<p>Lowercase: ${fn:toLowerCase(text)}</p>
<p>Substring: ${fn:substring(text, 0, 5)}</p>
<p>Index of 'World': ${fn:indexOf(text, 'World')}</p>
<p>Contains 'JSP': ${fn:contains(text, 'JSP')}</p>
<p>Starts with 'Hello': ${fn:startsWith(text, 'Hello')}</p>
<p>Ends with 'JSP': ${fn:endsWith(text, 'JSP')}</p>
<!-- String manipulation -->
<h3>String Manipulation</h3>
<p>Replace: ${fn:replace(text, 'World', 'Universe')}</p>
<p>Trim: "${fn:trim(' spaced text ')}"</p>
<!-- Split example -->
<c:set var="colors" value="red,green,blue,yellow" />
<h3>Split Example</h3>
<p>Colors: ${colors}</p>
<c:set var="colorArray" value="${fn:split(colors, ',')}" />
<ul>
<c:forEach var="color" items="${colorArray}">
<li>${color}</li>
</c:forEach>
</ul>
<!-- Escape XML -->
<h3>XML Escaping</h3>
<c:set var="xmlData" value="<tag>content & more</tag>" />
<p>Original: ${xmlData}</p>
<p>Escaped: ${fn:escapeXml(xmlData)}</p>
</body>
</html>
Custom Tags
Simple Custom Tag
// HelloTag.java
package com.example.tags;
import jakarta.servlet.jsp.*;
import jakarta.servlet.jsp.tagext.*;
import java.io.IOException;
public class HelloTag extends SimpleTagSupport {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void doTag() throws JspException, IOException {
JspWriter out = getJspContext().getOut();
if (name != null) {
out.println("Hello, " + name + "!");
} else {
out.println("Hello, World!");
}
}
}
<!-- WEB-INF/custom.tld -->
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<tlib-version>1.0</tlib-version>
<short-name>custom</short-name>
<uri>http://example.com/tags</uri>
<tag>
<name>hello</name>
<tag-class>com.example.tags.HelloTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>name</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
<!-- Using the custom tag -->
<%@ taglib prefix="custom" uri="http://example.com/tags" %>
<!DOCTYPE html>
<html>
<body>
<h2>Custom Tag Example</h2>
<p><custom:hello /></p>
<p><custom:hello name="John" /></p>
<p><custom:hello name="${param.username}" /></p>
</body>
</html>
Advanced Custom Tag with Body
// HighlightTag.java
package com.example.tags;
import jakarta.servlet.jsp.*;
import jakarta.servlet.jsp.tagext.*;
import java.io.IOException;
import java.io.StringWriter;
public class HighlightTag extends SimpleTagSupport {
private String color = "yellow";
public void setColor(String color) {
this.color = color;
}
@Override
public void doTag() throws JspException, IOException {
JspWriter out = getJspContext().getOut();
StringWriter stringWriter = new StringWriter();
// Process the body content
getJspBody().invoke(stringWriter);
String bodyContent = stringWriter.toString();
// Output highlighted content
out.println("<span style=\"background-color: " + color + ";\">");
out.println(bodyContent);
out.println("</span>");
}
}
<%@ taglib prefix="custom" uri="http://example.com/tags" %>
<!DOCTYPE html>
<html>
<body>
<h2>Advanced Custom Tag</h2>
<p>This is normal text.</p>
<p>This is <custom:highlight>highlighted text</custom:highlight> in the paragraph.</p>
<p>This is <custom:highlight color="lightblue">blue highlighted text</custom:highlight>.</p>
<custom:highlight color="lightgreen">
<h3>This entire section is highlighted</h3>
<p>Including this paragraph and any nested content.</p>
</custom:highlight>
</body>
</html>
JSP Lifecycle
JSP to Servlet Conversion
<!-- example.jsp -->
<%@ page contentType="text/html; charset=UTF-8" %>
<%!
private int counter = 0;
public String getGreeting() {
return "Hello from JSP!";
}
%>
<!DOCTYPE html>
<html>
<body>
<h1><%= getGreeting() %></h1>
<p>This page has been accessed <%= ++counter %> times.</p>
<p>Current time: <%= new java.util.Date() %></p>
</body>
</html>
The above JSP gets converted to a servlet similar to:
// Generated servlet (conceptual)
public class example_jsp extends HttpJspBase {
// From declaration section
private int counter = 0;
public String getGreeting() {
return "Hello from JSP!";
}
public void _jspService(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html; charset=UTF-8");
JspWriter out = pageContext.getOut();
out.write("<!DOCTYPE html>\n");
out.write("<html>\n");
out.write("<body>\n");
out.write(" <h1>");
out.print(getGreeting());
out.write("</h1>\n");
out.write(" <p>This page has been accessed ");
out.print(++counter);
out.write(" times.</p>\n");
out.write(" <p>Current time: ");
out.print(new java.util.Date());
out.write("</p>\n");
out.write("</body>\n");
out.write("</html>\n");
}
}
Best Practices
1. Separation of Concerns
<!-- Bad: Business logic in JSP -->
<%@ page import="java.sql.*" %>
<%
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb", "user", "pass");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
%>
<!-- Good: Use servlets/controllers for business logic -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- UserController servlet prepares data and forwards to JSP -->
<table>
<c:forEach var="user" items="${users}">
<tr>
<td>${user.name}</td>
<td>${user.email}</td>
</tr>
</c:forEach>
</table>
2. Use EL and JSTL Instead of Scriptlets
<!-- Bad: Scriptlets -->
<%
String username = (String) session.getAttribute("username");
if (username != null) {
%>
<p>Welcome, <%= username %>!</p>
<%
} else {
%>
<p>Please log in.</p>
<%
}
%>
<!-- Good: EL and JSTL -->
<c:choose>
<c:when test="${not empty sessionScope.username}">
<p>Welcome, ${sessionScope.username}!</p>
</c:when>
<c:otherwise>
<p>Please log in.</p>
</c:otherwise>
</c:choose>
3. Error Handling
<!-- error.jsp -->
<%@ page isErrorPage="true" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<title>Error Page</title>
<style>
.error { color: red; border: 1px solid red; padding: 10px; }
</style>
</head>
<body>
<h1>An Error Occurred</h1>
<div class="error">
<h3>Error Details:</h3>
<p><strong>Type:</strong> ${pageContext.exception.class.name}</p>
<p><strong>Message:</strong> ${pageContext.exception.message}</p>
<% if (application.getInitParameter("debug").equals("true")) { %>
<h4>Stack Trace:</h4>
<pre>
<% exception.printStackTrace(new java.io.PrintWriter(out)); %>
</pre>
<% } %>
</div>
<p><a href="${pageContext.request.contextPath}/">Return to Home</a></p>
</body>
</html>
<!-- In other JSPs -->
<%@ page errorPage="error.jsp" %>
4. Security Considerations
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!-- Always escape user input to prevent XSS -->
<p>Hello, <c:out value="${param.username}" escapeXml="true" />!</p>
<!-- Or using EL with fn:escapeXml -->
<p>Comment: ${fn:escapeXml(param.comment)}</p>
<!-- Validate and sanitize data -->
<c:if test="${not empty param.age and param.age matches '^[0-9]+$'}">
<p>Age: ${param.age}</p>
</c:if>
<!-- Use HTTPS for sensitive operations -->
<c:if test="${not pageContext.request.secure}">
<c:redirect url="https://${pageContext.request.serverName}${pageContext.request.requestURI}" />
</c:if>
5. Performance Optimization
<!-- Use page directive for caching -->
<%@ page buffer="8kb" autoFlush="false" %>
<!-- Minimize scriptlet usage -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- Use c:out for simple output -->
<c:out value="${user.name}" default="Anonymous" />
<!-- Efficient iteration -->
<c:forEach var="item" items="${items}" varStatus="status">
<tr class="${status.index % 2 == 0 ? 'even' : 'odd'}">
<td>${item.name}</td>
<td>${item.value}</td>
</tr>
</c:forEach>
<!-- Conditional inclusion -->
<c:if test="${user.isAdmin}">
<jsp:include page="admin-panel.jsp" />
</c:if>
Summary
JSP provides a powerful way to create dynamic web content while maintaining separation between presentation and business logic:
Key Benefits:
- Simplified dynamic content generation
- Integration with Java ecosystem
- Built-in support for sessions and request handling
- Extensive tag library support (JSTL)
Best Practices:
- Use EL and JSTL instead of scriptlets
- Separate business logic into servlets/controllers
- Always escape user input for security
- Implement proper error handling
- Optimize for performance
Modern Usage: While modern frameworks like Spring Boot with Thymeleaf or React frontends have become more popular, JSP remains important for:
- Legacy application maintenance
- Understanding Java web fundamentals
- Rapid prototyping
- Educational purposes
Understanding JSP helps developers grasp the fundamentals of server-side rendering and provides insight into how modern frameworks abstract these concepts.