JSP syntax combines template text, directives, Expression Language, and tag libraries. Modern pages should render controller-provided data with EL and tags; declarations, scriptlets, and Java expressions are legacy constructs to recognize and remove.
HTML, whitespace, and other template text are written to the response. A page directive configures translation-time settings such as content type, character encoding, imports, session participation, and error-page behavior. Directives affect the generated Servlet; they are not output to the browser.
Use UTF-8 consistently in the page directive, HTML metadata, request decoding, and response. Include directives copy source during translation, while jsp:include performs a request-time include; choose based on whether the included output must be generated for each request.
EL uses ${...} for immediate evaluation and resolves values through page, request, session, and application scopes. Property syntax such as ${order.customer.name} reads bean properties or map entries, while bracket syntax handles dynamic keys. The empty operator checks null, empty strings, collections, arrays, and maps.
Use explicit scope objects when the same name could exist in several scopes: ${requestScope.user}, ${sessionScope.user}, or ${param.id}. EL is for safe view expressions, not database calls or large business calculations. Escape untrusted text before placing it into HTML, attributes, JavaScript, CSS, or URLs; each output context has different rules.
A declaration <%! ... %> creates fields or methods on the generated Servlet, a scriptlet <% ... %> inserts Java into the service method, and an expression <%= ... %> writes a Java value. These constructs share Servlet threading concerns, blur view and controller responsibilities, and make templates hard to review.
When maintaining an old page, move request processing to a Servlet or service, expose the result as attributes, replace Java conditions and loops with JSTL, and replace output expressions with escaped EL. Never store per-request mutable state in a JSP declaration because one generated Servlet instance may serve concurrent requests.
A JSP comment <%-- --%> is removed during translation and never reaches the client. An HTML comment is included in the response and can expose notes or EL output in page source. Use JSP comments for server-side implementation notes.
Literal ${ text may need escaping when it should not be interpreted as EL. Keep templates readable by avoiding deeply nested expressions, hidden coercions, and long ternaries. Compute complex display state in the controller and expose a clearly named value.
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<h1>Order ${requestScope.order.id}</h1>
<c:choose>
<c:when test="${empty requestScope.order.items}">
<p>No items.</p>
</c:when>
<c:otherwise>
<ul>
<c:forEach var="item" items="${requestScope.order.items}">
<li><c:out value="${item.name}" /></li>
</c:forEach>
</ul>
</c:otherwise>
</c:choose>
<%-- Avoid new code in this style. --%>
<%! private int sharedCounter = 0; %>
<% sharedCounter++; %>
<p><%= sharedCounter %></p>
The first is JSP Expression Language and resolves scoped data without embedding Java. The second is a legacy Java expression inserted into the generated Servlet.
No. HTML comments are sent to the browser. Use a JSP comment when the content must be removed on the server.
Explore 500+ free tutorials across 20+ languages and frameworks.