你需要知道的关于Java编程工具和API的一切,包括代码和例子。
作为最初的Java网络技术之一,JSP仍然被广泛使用,与Servlets和JSTL一起使用。这里介绍如何使用JSP来构建连接到Java后端的动态网页。

AnthiaCumming / Getty Images
目录
显示更多
雅加达服务器页(原名JavaServer Pages)是一种Java标准技术,开发者用它来为Java网络应用程序编写动态的、数据驱动的网页。JSP建立在Java Servlet(又称 Jakarta Servlet)规范之上,是Jakarta EE中包含的持续支持和升级的Java网络技术之一。
JSP和servlet通常是一起工作的,特别是在旧的Java Web应用程序中。从编码的角度来看,JSP和servlets之间最明显的区别是,用servlets你写Java代码,然后把客户端的标记(如HTML)嵌入到该代码中。对于JSP,你从客户端的脚本或标记开始,然后嵌入JSP标记,将你的页面连接到Java后端。
把JSP看作是一种写标记的方式,具有与后端交互的超级能力。通常,像HTML这样的标记被发送到客户端,在那里它通过JavaScript与后端服务器进行交互。JSP用特殊的命令对HTML进行预处理,以访问和使用服务器的功能,然后将编译后的页面发送给客户端。
JSP和JSF
JSP与JSF,即Jakarta Server Faces(以前是JavaServer Faces)密切相关。JSF是一种用于构建模型-视图-控制器(MVC)Web应用程序的Java规范。它是Eclipse Mojarra、MyFaces和PrimeFaces等Java Web框架的标准。虽然经常看到JSP被用作老式JSF应用程序的前端,但Facelets是现代JSF实现的首选视图技术。
开发人员还在使用JSP吗?
开发人员确实仍在为一些应用程序使用JSP。与Jamstack等现代方法或Thymeleaf等模板引擎相比,它是一种更简单的技术,但有时简单才是王道。
JSP是一种核心的Java网络技术。作为开发者,我们可以相对快速和容易地建立JSP页面,而且它们与Tomcat这样的Servlet容器中的Servlet无缝交互。你可以说,JSP是Java生态系统中相当于.NET世界中的PHP和ASP。
你会在旧的Java网络应用中遇到JSP。时不时地,你可能仍然会发现它对构建简单的、动态的Java网页很有用。作为一个Java开发者,你应该熟悉JSP以及如何在你的程序中使用它。
编写JSP页面
一个简单的JSP页面由嵌入JSP标签的HTML标记组成。JSP文件的扩展名是.jsp。JSP服务器(也称为JSP容器)被配置为将HTTP请求引导到一个特定的JSP页面,然后负责呈现HTTP响应。
当请求到达时,文件在服务器上被处理,HTML被渲染成应用视图,即网页。嵌入的JSP标签将被用来调用服务器端的代码和数据。JSP的最终产品是客户浏览器可以理解的原样的香草HTML。图1中的图表显示了HTML、JSP和Web应用服务器之间的互动。
IDG
图1.网络应用程序中的Jakarta服务器页面(JSP)的概述。
清单1显示了一个简单的JSP页面。
清单1.一个简单的JSP页面
<html>
<body>
<p>${2 * 2} should equal 4</p>
</body>
</html>
在这里,你看到一个包括JSP表达式的HTML块,它是一个用表达式语言(EL)写给Java服务器的指令。在表达式${2 * 2} ,${} 是JSP的语法,用于将代码插入HTML中。带大括号的美元符号告诉JSP处理器。"等一下,我们即将开始讨论一些你需要处理的特殊问题。" 当执行时,JSP页面将输出执行表达式中的任何内容的结果。在这种情况下,输出的结果将是数字4。
在Servlet容器中的JSP
JSP页面必须部署在一个servlet容器内。为了部署一个基于JSP和servlet的Java网络应用程序,你将把你的.jsp文件、Java代码和应用程序元数据打包在一个.war文件中,这是一个简单的.zip文件,具有网络应用程序的常规结构。
一旦你把JSP加载到你的servlet容器中,它就会被编译成servlet。JSP和servlet有相似的特点,包括访问和响应请求对象的能力。
如何在Tomcat中使用JSP
我们将使用Tomcat中的一个示例应用程序来让你开始使用Jakarta Server Pages。如果你还没有安装Tomcat,请浏览Tomcat下载页面,选择适合你操作系统的Tomcat安装。截至目前,Tomcat 10是当前版本,与Jakarta Servlet 6和Jakarta Server Pages 3.1兼容。
你可以把Tomcat安装成一个Windows服务,或者从命令行中用/bin/catalina.sh start或/bin/catalina.bat 。无论哪种方式,都要启动Tomcat,然后进入localhost:8080,看到图2所示的Tomcat欢迎页面。
IDG
图2.Tomcat的欢迎页面。
JSP中的隐式对象
在Tomcat的欢迎页面上,点击例子链接,然后点击JSP例子。
接下来,打开Implicit Objects Execute网络应用程序。图3显示了这个例子应用程序的输出。花点时间研究一下这个输出。它所描述的元素在JSP页面中默认总是可用的。
IDG
图3.一个JSP页面的输出样本。
请求参数
隐式对象是通过JSP页面访问的内置对象。当你在开发一个网页时,你将使用这些对象来访问诸如请求参数之类的东西,这些参数是在发出HTTP请求时从客户浏览器发送过来的数据。
考虑一下Implicit Objects应用程序的浏览器URL:http://localhost:8080/examples/jsp/jsp2/el/implicit-objects.jsp?foo=bar。
注意,这个页面没有什么特别之处;我们只是用它来看看URL参数是如何被访问的。参数是?foo=bar ,你可以看到它反映在网页的输出中,表格中显示的是EL表达式,值是bar 。要测试这一点,把URL改成http://localhost:8080/examples/jsp/jsp2/el/implicit-objects.jsp?foo=zork,点击*回车键*,你会看到输出中反映的变化。
这个例子是对使用JSP标签访问服务器端请求参数的一个非常简单的介绍。在这个例子中,JSP页面使用内置的(隐含的)名为param 的对象来访问Web应用程序的请求参数。param 对象在你在清单1中看到的JSP表达式语法里面是可用的。在那个例子中,我们用一个表达式来做一些数学运算。${2 * 2}在这个例子中,表达式被用来访问一个对象和该对象的一个字段:${param.foo} 。接下来,我们将更仔细地看一下隐式对象的例子。
Web应用程序中的JSP
在Implicit Objects页面上,点击后退箭头,然后是Source链接。这将引导你进入 Implicit Objects 网页应用程序的 JSP 代码,如清单 2 所示。
清单2.Implicit Objects网络应用程序的JSP代码
<%@page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<html>
<head>
<title>JSP 2.0 Expression Language - Implicit Objects</title>
</head>
<body>
<h1>JSP 2.0 Expression Language - Implicit Objects</h1>
<hr>
This example illustrates some of the implicit objects available
in the Expression Language. The following implicit objects are
available (not all illustrated here):
<ul>
<li>pageContext - the PageContext object</li>
<li>pageScope - a Map that maps page-scoped attribute names to
their values</li>
<li>requestScope - a Map that maps request-scoped attribute names
to their values</li>
<li>sessionScope - a Map that maps session-scoped attribute names
to their values</li>
<li>applicationScope - a Map that maps application-scoped attribute
names to their values</li>
<li>param - a Map that maps parameter names to a single String
parameter value</li>
<li>paramValues - a Map that maps parameter names to a String[] of
all values for that parameter</li>
<li>header - a Map that maps header names to a single String
header value</li>
<li>headerValues - a Map that maps header names to a String[] of
all values for that header</li>
<li>initParam - a Map that maps context initialization parameter
names to their String parameter value</li>
<li>cookie - a Map that maps cookie names to a single Cookie object.</li>
</ul>
<blockquote>
<u><b>Change Parameter</b></u>
<form action="implicit-objects.jsp" method="GET">
foo = <input type="text" name="foo" value="${fn:escapeXml(param["foo"])}">
<input type="submit">
</form>
<br>
<code>
<table border="1">
<thead>
<td><b>EL Expression</b></td>
<td><b>Result</b></td>
</thead>
<tr>
<td>\${param.foo}</td>
<td>${fn:escapeXml(param["foo"])} </td>
</tr>
<tr>
<td>\${param["foo"]}</td>
<td>${fn:escapeXml(param["foo"])} </td>
</tr>
<tr>
<td>\${header["host"]}</td>
<td>${fn:escapeXml(header["host"])} </td>
</tr>
<tr>
<td>\${header["accept"]}</td>
<td>${fn:escapeXml(header["accept"])} </td>
</tr>
<tr>
<td>\${header["user-agent"]}</td>
<td>${fn:escapeXml(header["user-agent"])} </td>
</tr>
</table>
</code>
</blockquote>
</body>
</html>
JSP功能
如果你熟悉HTML,那么清单2中的代码应该是相当容易理解的。你有预期的HTML<td> 元素,然后是清单1中介绍的${ } JSP表达式语法。但是请注意param.foo 的值。
<td>${fn:escapeXml(param["foo"])} </td>
这里,fn:escapeXML() 是一个JSP函数。
一个JSP函数封装了一大块可重用的功能。在这个例子中,这个功能是为了转义XML。JSP提供了各种各样的函数,你也可以自己创建函数。要使用一个函数,你要把它的库导入你的JSP页面,然后调用该函数。
在清单2中,我们用下面一行包括了escapeXML 函数。
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
语法非常清楚:它导入了所需的函数,并给它们分配了一个前缀(在这里是 "fn"),可以在所有下面的表达中使用。
雅加达标准标签库(JSTL)
清单 2 中的导入行调用taglib ,这是标签库的简称。在这种情况下,我们已经导入了雅加达标准标签库(JSTL)。标签库为JSP定义了可重复使用的功能位。JSTL是标准的标签库,包含了每个servlet和JSP实现(包括Tomcat)都有的标签集合。
函数 "库只是JSTL中的一个标签库。另一个常见的标签库是核心库,你可以通过调用来导入它。
<%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c" %>
就像"fn" ,"c" 的指定是常规的;你会在大多数JSP页面上看到它。
用JSTL保证JSP页面的安全
下面这个例子的标签来自JSTL核心库。
<c:out value = "${'<div>'}"/>