See More

# JSP 指南 ## 简介 ### 什么是 Java Server Pages `JSP`全称`Java Server Pages`,是一种动态网页开发技术。 它使用 JSP 标签在 HTML 网页中插入 Java 代码。标签通常以`<%`开头以`%>`结束。 JSP 是一种 Java servlet,主要用于实现 Java web 应用程序的用户界面部分。网页开发者们通过结合 HTML 代码、XHTML 代码、XML 元素以及嵌入 JSP 操作和命令来编写 JSP。 JSP 通过网页表单获取用户输入数据、访问数据库及其他数据源,然后动态地创建网页。 JSP 标签有多种功能,比如访问数据库、记录用户选择信息、访问 JavaBeans 组件等,还可以在不同的网页中传递控制信息和共享信息。 ### 为什么使用 JSP JSP 也是一种 Servlet,因此 JSP 能够完成 Servlet 能完成的任何工作。 JSP 程序与 CGI 程序有着相似的功能,但和 CGI 程序相比,JSP 程序有如下优势: - 性能更加优越,因为 JSP 可以直接在 HTML 网页中动态嵌入元素而不需要单独引用 CGI 文件。 - 服务器调用的是已经编译好的 JSP 文件,而不像 CGI/Perl 那样必须先载入解释器和目标脚本。 - JSP 基于 Java Servlets API,因此,JSP 拥有各种强大的企业级 Java API,包括 JDBC,JNDI,EJB,JAXP 等等。 - JSP 页面可以与处理业务逻辑的 servlets 一起使用,这种模式被 Java servlet 模板引擎所支持。 最后,JSP 是 Java EE 不可或缺的一部分,是一个完整的企业级应用平台。这意味着 JSP 可以用最简单的方式来实现最复杂的应用。 ### JSP 的优势 以下列出了使用 JSP 带来的其他好处: - 与 ASP 相比:JSP 有两大优势。首先,动态部分用 Java 编写,而不是 VB 或其他 MS 专用语言,所以更加强大与易用。第二点就是 JSP 易于移植到非 MS 平台上。 - 与纯 Servlets 相比:JSP 可以很方便的编写或者修改 HTML 网页而不用去面对大量的 println 语句。 - 与 SSI 相比:SSI 无法使用表单数据、无法进行数据库链接。 - 与 JavaScript 相比:虽然 JavaScript 可以在客户端动态生成 HTML,但是很难与服务器交互,因此不能提供复杂的服务,比如访问数据库和图像处理等等。 - 与静态 HTML 相比:静态 HTML 不包含动态信息。 ## JSP 工作原理 **JSP 是一种 Servlet**,但工作方式和 Servlet 有所差别。 Servlet 是先将源代码编译为 class 文件后部署到服务器下的,**先编译后部署**。 Jsp 是先将源代码部署到服务器再编译,**先部署后编译**。 Jsp 会在客户端第一次请求 Jsp 文件时被编译为 HttpJspPage 类(Servlet 的一个子类)。该类会被服务器临时存放在服务器工作目录里。所以,第一次请求 Jsp 后,访问速度会变快就是这个道理。 ### JSP 工作流程 网络服务器需要一个 JSP 引擎,也就是一个容器来处理 JSP 页面。容器负责截获对 JSP 页面的请求。本教程使用内嵌 JSP 容器的 Apache 来支持 JSP 开发。 JSP 容器与 Web 服务器协同合作,为 JSP 的正常运行提供必要的运行环境和其他服务,并且能够正确识别专属于 JSP 网页的特殊元素。 下图显示了 JSP 容器和 JSP 文件在 Web 应用中所处的位置。 ![img](http://www.runoob.com/wp-content/uploads/2014/01/jsp-arch.jpg) #### 工作步骤 以下步骤表明了 Web 服务器是如何使用 JSP 来创建网页的: - 就像其他普通的网页一样,您的浏览器发送一个 HTTP 请求给服务器。 - Web 服务器识别出这是一个对 JSP 网页的请求,并且将该请求传递给 JSP 引擎。通过使用 URL 或者.jsp 文件来完成。 - JSP 引擎从磁盘中载入 JSP 文件,然后将它们转化为 servlet。这种转化只是简单地将所有模板文本改用 println()语句,并且将所有的 JSP 元素转化成 Java 代码。 - JSP 引擎将 servlet 编译成可执行类,并且将原始请求传递给 servlet 引擎。 - Web 服务器的某组件将会调用 servlet 引擎,然后载入并执行 servlet 类。在执行过程中,servlet 产生 HTML 格式的输出并将其内嵌于 HTTP response 中上交给 Web 服务器。 - Web 服务器以静态 HTML 网页的形式将 HTTP response 返回到您的浏览器中。 - 最终,Web 浏览器处理 HTTP response 中动态产生的 HTML 网页,就好像在处理静态网页一样。 以上提及到的步骤可以用下图来表示: 一般情况下,JSP 引擎会检查 JSP 文件对应的 servlet 是否已经存在,并且检查 JSP 文件的修改日期是否早于 servlet。如果 JSP 文件的修改日期早于对应的 servlet,那么容器就可以确定 JSP 文件没有被修改过并且 servlet 有效。这使得整个流程与其他脚本语言(比如 PHP)相比要高效快捷一些。 ### JSP 生命周期 理解 JSP 底层功能的关键就是去理解它们所遵守的生命周期。 JSP 生命周期就是从创建到销毁的整个过程,类似于 servlet 生命周期,区别在于 JSP 生命周期还包括将 JSP 文件编译成 servlet。 以下是 JSP 生命周期中所走过的几个阶段: - **编译阶段:**servlet 容器编译 servlet 源文件,生成 servlet 类 - **初始化阶段:**加载与 JSP 对应的 servlet 类,创建其实例,并调用它的初始化方法 - **执行阶段:**调用与 JSP 对应的 servlet 实例的服务方法 - **销毁阶段:**调用与 JSP 对应的 servlet 实例的销毁方法,然后销毁 servlet 实例 很明显,JSP 生命周期的四个主要阶段和 servlet 生命周期非常相似,下面给出图示: ![img](http://www.runoob.com/wp-content/uploads/2014/01/jsp_life_cycle.jpg) #### JSP 编译 当浏览器请求 JSP 页面时,JSP 引擎会首先去检查是否需要编译这个文件。如果这个文件没有被编译过,或者在上次编译后被更改过,则编译这个 JSP 文件。 编译的过程包括三个步骤: - 解析 JSP 文件。 - 将 JSP 文件转为 servlet。 - 编译 servlet。 #### JSP 初始化 容器载入 JSP 文件后,它会在为请求提供任何服务前调用 jspInit()方法。如果您需要执行自定义的 JSP 初始化任务,复写 jspInit()方法就行了,就像下面这样: ```java public void jspInit(){ // 初始化代码 } ``` 一般来讲程序只初始化一次,servlet 也是如此。通常情况下您可以在 jspInit()方法中初始化数据库连接、打开文件和创建查询表。 #### JSP 执行 这一阶段描述了 JSP 生命周期中一切与请求相关的交互行为,直到被销毁。 当 JSP 网页完成初始化后,JSP 引擎将会调用 `_jspService()` 方法。 `_jspService()` 方法需要一个 HttpServletRequest 对象和一个 HttpServletResponse 对象作为它的参数,就像下面这样: ```java void _jspService(HttpServletRequest request, HttpServletResponse response) { // 服务端处理代码 } ``` `_jspService()` 方法在每个 request 中被调用一次并且负责产生与之相对应的 response,并且它还负责产生所有 7 个 HTTP 方法的回应,比如 GET、POST、DELETE 等等。 #### JSP 清理 JSP 生命周期的销毁阶段描述了当一个 JSP 网页从容器中被移除时所发生的一切。 jspDestroy()方法在 JSP 中等价于 servlet 中的销毁方法。当您需要执行任何清理工作时复写 jspDestroy()方法,比如释放数据库连接或者关闭文件夹等等。 jspDestroy()方法的格式如下: ```java public void jspDestroy() { // 清理代码 } ``` ## 语法 ### 脚本 脚本程序可以包含任意量的 Java 语句、变量、方法或表达式,只要它们在脚本语言中是有效的。 脚本程序的语法格式: ``` <% 代码片段 %> ``` 或者,您也可以编写与其等价的 XML 语句,就像下面这样: ``` 代码片段 ``` 任何文本、HTML 标签、JSP 元素必须写在脚本程序的外面。 下面给出一个示例,同时也是本教程的第一个 JSP 示例: ```

Hello World Hello World!
<% out.println("Your IP address is " + request.getRemoteAddr()); %> ``` **注意:**请确保 Apache Tomcat 已经安装在 C:\apache-tomcat-7.0.2 目录下并且运行环境已经正确设置。 将以上代码保存在 hello.jsp 中,然后将它放置在 C:\apache-tomcat-7.0.2\webapps\ROOT 目录下,打开浏览器并在地址栏中输入 `http://localhost:8080/hello.jsp` 。运行后得到以下结果: ![img](http://www.runoob.com/wp-content/uploads/2014/01/jsp_hello_world.jpg) #### 中文编码问题 如果我们要在页面正常显示中文,我们需要在 JSP 文件头部添加以下代码:`<>` ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> ``` 接下来我们将以上程序修改为: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 菜鸟教程(runoob.com) Hello World!
<% out.println("你的 IP 地址 " + request.getRemoteAddr()); %> ``` 这样中文就可以正常显示了。 ### JSP 声明 一个声明语句可以声明一个或多个变量、方法,供后面的 Java 代码使用。在 JSP 文件中,您必须先声明这些变量和方法然后才能使用它们。 JSP 声明的语法格式: ``` <%! declaration; [ declaration; ]+ ... %> ``` 或者,您也可以编写与其等价的 XML 语句,就像下面这样: ``` 代码片段 ``` 程序示例: ``` <%! int i = 0; %> <%! int a, b, c; %> <%! Circle a = new Circle(2.0); %> ``` ### JSP 表达式 一个 JSP 表达式中包含的脚本语言表达式,先被转化成 String,然后插入到表达式出现的地方。 由于表达式的值会被转化成 String,所以您可以在一个文本行中使用表达式而不用去管它是否是 HTML 标签。 表达式元素中可以包含任何符合 Java 语言规范的表达式,但是不能使用分号来结束表达式。 JSP 表达式的语法格式: ``` <%= 表达式 %> ``` 同样,您也可以编写与之等价的 XML 语句: ``` 表达式 ``` 程序示例: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 菜鸟教程(runoob.com)

今天的日期是: <%= (new java.util.Date()).toLocaleString()%>

``` 运行后得到以下结果: ``` 今天的日期是: 2016-6-25 13:40:07 ``` --- ### JSP 注释 JSP 注释主要有两个作用:为代码作注释以及将某段代码注释掉。 JSP 注释的语法格式: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> JSP注释示例 <%-- 该部分注释在网页中不会被显示--%>

今天的日期是: <%= (new java.util.Date()).toLocaleString()%>

``` 运行后得到以下结果: ``` 今天的日期是: 2016-6-25 13:41:26 ``` 不同情况下使用注释的语法规则: | **语法** | 描述 | | ---------------- | ----------------------------------------------------- | | `<%-- 注释 --%>` | JSP 注释,注释内容不会被发送至浏览器甚至不会被编译 | | `` | HTML 注释,通过浏览器查看网页源代码时可以看见注释内容 | | `<%` | 代表静态 <%常量 | | `%>` | 代表静态 %> 常量 | | `'` | 在属性中使用的单引号 | | `"` | 在属性中使用的双引号 | ### 控制语句 JSP 提供对 Java 语言的全面支持。您可以在 JSP 程序中使用 Java API 甚至建立 Java 代码块,包括判断语句和循环语句等等。 #### if…else 语句 `If…else`块,请看下面这个例子: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%! int day = 1; %> 02.JSP语法 - if...else示例

IF...ELSE 实例

<% if (day == 1 | day == 7) { %>

今天是周末

<% } else { %>

今天不是周末

<% } %> ``` 运行后得到以下结果: ``` IF...ELSE 实例 今天不是周末 ``` #### switch…case 语句 现在来看看 switch…case 块,与 if…else 块有很大的不同,它使用 out.println(),并且整个都装在脚本程序的标签中,就像下面这样: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%! int day = 3; %> 02.JSP语法 - switch...case示例

Sswitch...case示例

<% switch(day) { case 0: out.println("星期天"); break; case 1: out.println("星期一"); break; case 2: out.println("星期二"); break; case 3: out.println("星期三"); break; case 4: out.println("星期四"); break; case 5: out.println("星期五"); break; default: out.println("星期六"); } %> ``` 浏览器访问,运行后得出以下结果: ``` SWITCH...CASE 实例 星期三 ``` #### 循环语句 在 JSP 程序中可以使用 Java 的三个基本循环类型:for,while,和 do…while。 让我们来看看 for 循环的例子,以下输出的不同字体大小的"菜鸟教程": ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%! int fontSize; %> 菜鸟教程(runoob.com)

For 循环实例

<%for ( fontSize = 1; fontSize <= 3; fontSize++){ %> 菜鸟教程
<%}%> ``` 运行后得到以下结果: ![img](http://www.runoob.com/wp-content/uploads/2014/01/7B4B85CF-FE4B-43CB-AAFF-F8594AD4342C.jpg) 将上例改用 while 循环来写: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%! int fontSize; %> 菜鸟教程(runoob.com)

While 循环实例

<%while ( fontSize <= 3){ %> 菜鸟教程
<%fontSize++;%> <%}%> ``` 浏览器访问,输出结果为(fontSize 初始化为 0,所以多输出了一行): ![img](http://www.runoob.com/wp-content/uploads/2014/01/4F744CC9-E484-45BA-AF18-27AFCF4AD45C.jpg) JSP 运算符 JSP 支持所有 Java 逻辑和算术运算符。 下表罗列出了 JSP 常见运算符,优先级从高到底: | **类别** | **操作符** | **结合性** | | --------- | ----------------------------------- | ---------- | | 后缀 | `() [] .` (点运算符) | 左到右 | | 一元 | `++ - - ! ~` | 右到左 | | 可乘性 | `* / %` | 左到右 | | 可加性 | `+ -` | 左到右 | | 移位 | `>> >>> <<` | 左到右 | | 关系 | `> >= < <=` | 左到右 | | 相等/不等 | `== !=` | 左到右 | | 位与 | `&` | 左到右 | | 位异或 | `^` | 左到右 | | 位或 | `|` | 左到右 | | 逻辑与 | `&&` | 左到右 | | 逻辑或 | `||` | 左到右 | | 条件判断 | `?:` | 右到左 | | 赋值 | `= += -= *= /= %= >>= <<= &= ^= |=` | 右到左 | | 逗号 | `,` | 左到右 | ### JSP 字面量 JSP 语言定义了以下几个字面量: - 布尔值(boolean):true 和 false; - 整型(int):与 Java 中的一样; - 浮点型(float):与 Java 中的一样; - 字符串(string):以单引号或双引号开始和结束; - Null:null。 ## 指令 JSP 指令用来设置整个 JSP 页面相关的属性,如网页的编码方式和脚本语言。 JSP 指令以开`<%@`开始,以`%>`结束。 JSP 指令语法格式如下: ``` <%@ directive attribute="value" %> ``` 指令可以有很多个属性,它们以键值对的形式存在,并用逗号隔开。 JSP 中的三种指令标签: | **指令** | **描述** | | -------------------- | -------------------------------------------------------- | | `<%@ page ... %>` | 定义网页依赖属性,比如脚本语言、error 页面、缓存需求等等 | | `<%@ include ... %>` | 包含其他文件 | | `<%@ taglib ... %>` | 引入标签库的定义,可以是自定义标签 | ### Page 指令 Page 指令为容器提供当前页面的使用说明。一个 JSP 页面可以包含多个`page`指令。 Page 指令的语法格式: ``` <%@ page attribute="value" %> ``` 等价的 XML 格式: ``` ``` 例: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> ``` #### 属性 下表列出与 Page 指令相关的属性: | **属性** | **描述** | | ------------------ | ----------------------------------------------------- | | buffer | 指定 out 对象使用缓冲区的大小 | | autoFlush | 控制 out 对象的 缓存区 | | contentType | 指定当前 JSP 页面的 MIME 类型和字符编码 | | errorPage | 指定当 JSP 页面发生异常时需要转向的错误处理页面 | | isErrorPage | 指定当前页面是否可以作为另一个 JSP 页面的错误处理页面 | | extends | 指定 servlet 从哪一个类继承 | | import | 导入要使用的 Java 类 | | info | 定义 JSP 页面的描述信息 | | isThreadSafe | 指定对 JSP 页面的访问是否为线程安全 | | language | 定义 JSP 页面所用的脚本语言,默认是 Java | | session | 指定 JSP 页面是否使用 session | | isELIgnored | 指定是否执行 EL 表达式 | | isScriptingEnabled | 确定脚本元素能否被使用 | ### Include 指令 JSP 可以通过`include`指令来包含其他文件。 被包含的文件可以是 JSP 文件、HTML 文件或文本文件。包含的文件就好像是该 JSP 文件的一部分,会被同时编译执行。 Include 指令的语法格式如下: ``` <%@ include file="文件相对 url 地址" %> ``` **include** 指令中的文件名实际上是一个相对的 URL 地址。 如果您没有给文件关联一个路径,JSP 编译器默认在当前路径下寻找。 等价的 XML 语法: ``` ``` ### Taglib 指令 JSP 允许用户自定义标签,一个自定义标签库就是自定义标签的集合。 `taglib`指令引入一个自定义标签集合的定义,包括库路径、自定义标签。 `taglib`指令的语法: ``` <%@ taglib uri="uri" prefix="prefixOfTag" %> ``` uri 属性确定标签库的位置,prefix 属性指定标签库的前缀。 等价的 XML 语法: ``` ``` ## JSP 动作元素 JSP 动作元素是一组 JSP 内置的标签,只需要书写很少的标记代码就能使用 JSP 提供的丰富功能。JSP 动作元素是对常用的 JSP 功能的抽象与封装,包括两种,自定义 JSP 动作元素与标准 JSP 动作元素。 与 JSP 指令元素不同的是,JSP 动作元素在请求处理阶段起作用。JSP 动作元素是用 XML 语法写成的。 利用 JSP 动作可以动态地插入文件、重用 JavaBean 组件、把用户重定向到另外的页面、为 Java 插件生成 HTML 代码。 动作元素只有一种语法,它符合 XML 标准: ``` ``` 动作元素基本上都是预定义的函数,JSP 规范定义了一系列的标准动作,它用 JSP 作为前缀,可用的标准动作元素如下: | 语法 | 描述 | | --------------- | ----------------------------------------------------- | | jsp:include | 在页面被请求的时候引入一个文件。 | | jsp:useBean | 寻找或者实例化一个 JavaBean。 | | jsp:setProperty | 设置 JavaBean 的属性。 | | jsp:getProperty | 输出某个 JavaBean 的属性。 | | jsp:forward | 把请求转到一个新的页面。 | | jsp:plugin | 根据浏览器类型为 Java 插件生成 OBJECT 或 EMBED 标记。 | | jsp:element | 定义动态 XML 元素 | | jsp:attribute | 设置动态定义的 XML 元素属性。 | | jsp:body | 设置动态定义的 XML 元素内容。 | | jsp:text | 在 JSP 页面和文档中使用写入文本的模板 | ### 常见的属性 所有的动作要素都有两个属性:id 属性和 scope 属性。 - **id 属性:**id 属性是动作元素的唯一标识,可以在 JSP 页面中引用。动作元素创建的 id 值可以通过 PageContext 来调用。 - **scope 属性:**该属性用于识别动作元素的生命周期。 id 属性和 scope 属性有直接关系,scope 属性定义了相关联 id 对象的寿命。 scope 属性有四个可能的值: (a) page, (b)request, (c)session, 和 (d) application。 ### `` `` 用来包含静态和动态的文件。该动作把指定文件插入正在生成的页面。 如果被包含的文件为 JSP 程序,则会先执行 JSP 程序,再将执行结果包含进来。 语法格式如下: ``` ``` 前面已经介绍过 include 指令,它是在 JSP 文件被转换成 Servlet 的时候引入文件,而这里的 jsp:include 动作不同,插入文件的时间是在页面被请求的时候。 以下是 include 动作相关的属性列表。 | 属性 | 描述 | | ----- | ------------------------------------------ | | page | 包含在页面中的相对 URL 地址。 | | flush | 布尔属性,定义在包含资源前是否刷新缓存区。 | 示例: 以下我们定义了两个文件 **date.jsp** 和 **main.jsp**,代码如下所示: date.jsp 文件代码: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

今天的日期是: <%= (new java.util.Date())%>

``` main.jsp 文件代码: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 菜鸟教程(runoob.com)

include 动作实例

``` 现在将以上两个文件放在服务器的根目录下,访问 main.jsp 文件。显示结果如下: ``` include 动作实例 今天的日期是: 2016-6-25 14:08:17 ``` ### `` **jsp:useBean** 动作用来加载一个将在 JSP 页面中使用的 JavaBean。 这个功能非常有用,因为它使得我们可以发挥 Java 组件复用的优势。 jsp:useBean 动作最简单的语法为: ``` ``` 在类载入后,我们既可以通过 jsp:setProperty 和 jsp:getProperty 动作来修改和检索 bean 的属性。 以下是 useBean 动作相关的属性列表。 | 属性 | 描述 | | -------- | ------------------------------------------------------------- | | class | 指定 Bean 的完整包名。 | | type | 指定将引用该对象变量的类型。 | | beanName | 通过 java.beans.Beans 的 instantiate() 方法指定 Bean 的名字。 | 在给出具体实例前,让我们先来看下 jsp:setProperty 和 jsp:getProperty 动作元素: ### `` jsp:setProperty 用来设置已经实例化的 Bean 对象的属性,有两种用法。首先,你可以在 jsp:useBean 元素的外面(后面)使用 jsp:setProperty,如下所示: ``` ... ``` 此时,不管 jsp:useBean 是找到了一个现有的 Bean,还是新创建了一个 Bean 实例,jsp:setProperty 都会执行。第二种用法是把 jsp:setProperty 放入 jsp:useBean 元素的内部,如下所示: ``` ... ``` 此时,jsp:setProperty 只有在新建 Bean 实例时才会执行,如果是使用现有实例则不执行 jsp:setProperty。 jsp:setProperty 动作有下面四个属性,如下表: | 属性 | 描述 | | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | name | name 属性是必需的。它表示要设置属性的是哪个 Bean。 | | property | property 属性是必需的。它表示要设置哪个属性。有一个特殊用法:如果 property 的值是"\*",表示所有名字和 Bean 属性名字匹配的请求参数都将被传递给相应的属性 set 方法。 | | value | value 属性是可选的。该属性用来指定 Bean 属性的值。字符串数据会在目标类中通过标准的 valueOf 方法自动转换成数字、boolean、Boolean、 byte、Byte、char、Character。例如,boolean 和 Boolean 类型的属性值(比如"true")通过 Boolean.valueOf 转换,int 和 Integer 类型的属性值(比如"42")通过 Integer.valueOf 转换。    value 和 param 不能同时使用,但可以使用其中任意一个。 | | param | param 是可选的。它指定用哪个请求参数作为 Bean 属性的值。如果当前请求没有参数,则什么事情也不做,系统不会把 null 传递给 Bean 属性的 set 方法。因此,你可以让 Bean 自己提供默认属性值,只有当请求参数明确指定了新值时才修改默认属性值。 | ### `` jsp:getProperty 动作提取指定 Bean 属性的值,转换成字符串,然后输出。语法格式如下: ``` ... ``` 下表是与 getProperty 相关联的属性: | 属性 | 描述 | | -------- | ----------------------------------------- | | name | 要检索的 Bean 属性名称。Bean 必须已定义。 | | property | 表示要提取 Bean 属性的值 | 实例 以下实例我们使用了 Bean: ```java package com.runoob.main; public class TestBean { private String message = "菜鸟教程"; public String getMessage() { return(message); } public void setMessage(String message) { this.message = message; } } ``` 编译以上实例文件 TestBean.java : ``` $ javac TestBean.java ``` 编译完成后会在当前目录下生成一个 **TestBean.class** 文件, 将该文件拷贝至当前 JSP 项目的 **WebContent/WEB-INF/classes/com/runoob/main** 下( com/runoob/main 包路径,没有需要手动创建)。 下面是一个 Eclipse 中目录结构图: ![img](http://www.runoob.com/wp-content/uploads/2014/01/6AC33FBA-0B76-4BFD-A690-E856E9E01900.jpg) 下面是一个很简单的例子,它的功能是装载一个 Bean,然后设置/读取它的 message 属性。 现在让我们在 main.jsp 文件中调用该 Bean: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 菜鸟教程(runoob.com)

Jsp 使用 JavaBean 实例

输出信息....

``` 浏览器访问,执行以上文件,输出如下所示: ![img](http://www.runoob.com/wp-content/uploads/2014/01/D7AD87A8-3392-4D4E-8731-18806B0644CD.jpg) ### `` jsp:forward 动作把请求转到另外的页面。jsp:forward 标记只有一个属性 page。语法格式如下所示: ``` ``` 以下是 forward 相关联的属性: | 属性 | 描述 | | ---- | ----------------------------------------------------------------------------------------------------------------------------- | | page | page 属性包含的是一个相对 URL。page 的值既可以直接给出,也可以在请求的时候动态计算,可以是一个 JSP 页面或者一个 Java Servlet. | 实例 以下实例我们使用了两个文件,分别是: date.jsp 和 main.jsp。 date.jsp 文件代码如下: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

今天的日期是: <%= (new java.util.Date()).toLocaleString()%>

``` main.jsp 文件代码: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 菜鸟教程(runoob.com)

forward 动作实例

``` 现在将以上两个文件放在服务器的根目录下,访问 main.jsp 文件。显示结果如下: ``` 今天的日期是: 2016-6-25 14:37:25 ``` ### `` jsp:plugin 动作用来根据浏览器的类型,插入通过 Java 插件 运行 Java Applet 所必需的 OBJECT 或 EMBED 元素。 如果需要的插件不存在,它会下载插件,然后执行 Java 组件。 Java 组件可以是一个 applet 或一个 JavaBean。 plugin 动作有多个对应 HTML 元素的属性用于格式化 Java 组件。param 元素可用于向 Applet 或 Bean 传递参数。 以下是使用 plugin 动作元素的典型实例: ``` Unable to initialize Java Plugin ``` 如果你有兴趣可以尝试使用 applet 来测试 `jsp:plugin` 动作元素,`` 元素是一个新元素,在组件出现故障的错误是发送给用户错误信息。 ### `` 、 ``、`` `` 、 ``、`` 动作元素动态定义 XML 元素。动态是非常重要的,这就意味着 XML 元素在编译时是动态生成的而非静态。 以下实例动态定义了 XML 元素: ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 菜鸟教程(runoob.com) 属性值 XML 元素的主体 ``` 浏览器访问以下页面,输出结果如下所示: ![img](http://www.runoob.com/wp-content/uploads/2014/01/7D8C47F0-0DDE-4F1D-8BE1-B2C9C955683E.jpg) ### `` 动作元素允许在 JSP 页面和文档中使用写入文本的模板,语法格式如下: ``` 模板数据 ``` 以上文本模板不能包含其他元素,只能只能包含文本和 EL 表达式(注:EL 表达式将在后续章节中介绍)。请注意,在 XML 文件中,您不能使用表达式如 ${whatever > 0},因为>符号是非法的。 你可以使用 ${whatever gt 0}表达式或者嵌入在一个 CDATA 部分的值。 ``` <![CDATA[
]]>
``` 如果你需要在 XHTML 中声明 DOCTYPE,必须使用到 `` 动作元素,实例如下: ``` <![CDATA[]]> jsp:text action Welcome to JSP Programming

``` 你可以对以上实例尝试使用及不使用该动作元素执行结果的区别。 ## JSP 隐式对象 JSP 隐式对象是 JSP 容器为每个页面提供的 Java 对象,开发者可以直接使用它们而不用显式声明。JSP 隐式对象也被称为预定义变量。 JSP 所支持的九大隐式对象: | **对象** | **描述** | | ----------- | ------------------------------------------------------------------ | | request | **HttpServletRequest**类的实例 | | response | **HttpServletResponse**类的实例 | | out | **PrintWriter**类的实例,用于把结果输出至网页上 | | session | **HttpSession**类的实例 | | application | **ServletContext**类的实例,与应用上下文有关 | | config | **ServletConfig**类的实例 | | pageContext | **PageContext**类的实例,提供对 JSP 页面所有对象以及命名空间的访问 | | page | 类似于 Java 类中的 this 关键字 | | Exception | **Exception**类的对象,代表发生错误的 JSP 页面中对应的异常对象 | ### request 对象 `request`对象是`javax.servlet.http.HttpServletRequest` 类的实例。 每当客户端请求一个 JSP 页面时,JSP 引擎就会制造一个新的`request`对象来代表这个请求。 `request`对象提供了一系列方法来获取 HTTP 头信息,cookies,HTTP 方法等等。 ### response 对象 `response`对象是`javax.servlet.http.HttpServletResponse`类的实例。 当服务器创建`request`对象时会同时创建用于响应这个客户端的`response`对象。 `response`对象也定义了处理 HTTP 头模块的接口。通过这个对象,开发者们可以添加新的 cookies,时间戳,HTTP 状态码等等。 ### out 对象 `out`对象是`javax.servlet.jsp.JspWriter`类的实例,用来在`response`对象中写入内容。 最初的`JspWriter`类对象根据页面是否有缓存来进行不同的实例化操作。可以在`page`指令中使用`buffered='false'`属性来轻松关闭缓存。 `JspWriter`类包含了大部分`java.io.PrintWriter`类中的方法。不过,`JspWriter`新增了一些专为处理缓存而设计的方法。还有就是,`JspWriter`类会抛出`IOExceptions`异常,而`PrintWriter`不会。 下表列出了我们将会用来输出`boolean`,`char`,`int`,`double`,`String`,`object`等类型数据的重要方法: | **方法** | **描述** | | ---------------------------- | -------------------------- | | **out.print(dataType dt)** | 输出 Type 类型的值 | | **out.println(dataType dt)** | 输出 Type 类型的值然后换行 | | **out.flush()** | 刷新输出流 | ### session 对象 `session`对象是`javax.servlet.http.HttpSession`类的实例。和 Java Servlets 中的`session`对象有一样的行为。 `session`对象用来跟踪在各个客户端请求间的会话。 ### application 对象 `application`对象直接包装了 servlet 的`ServletContext`类的对象,是`javax.servlet.ServletContext`类的实例。 这个对象在 JSP 页面的整个生命周期中都代表着这个 JSP 页面。这个对象在 JSP 页面初始化时被创建,随着`jspDestroy()`方法的调用而被移除。 通过向`application`中添加属性,则所有组成您 web 应用的 JSP 文件都能访问到这些属性。 ### config 对象 `config`对象是`javax.servlet.ServletConfig`类的实例,直接包装了 servlet 的`ServletConfig`类的对象。 这个对象允许开发者访问 Servlet 或者 JSP 引擎的初始化参数,比如文件路径等。 以下是 config 对象的使用方法,不是很重要,所以不常用: ``` config.getServletName(); ``` 它返回包含在``元素中的 servlet 名字,注意,``元素在`WEB-INF\web.xml`文件中定义。 ### pageContext 对象 `pageContext`对象是`javax.servlet.jsp.PageContext`类的实例,用来代表整个 JSP 页面。 这个对象主要用来访问页面信息,同时过滤掉大部分实现细节。 这个对象存储了`request`对象和`response`对象的引用。`application`对象,`config`对象,`session`对象,`out`对象可以通过访问这个对象的属性来导出。 `pageContext`对象也包含了传给 JSP 页面的指令信息,包括缓存信息,ErrorPage URL,页面 scope 等。 `PageContext`类定义了一些字段,包括 PAGE_SCOPE,REQUEST_SCOPE,SESSION_SCOPE, APPLICATION_SCOPE。它也提供了 40 余种方法,有一半继承自`javax.servlet.jsp.JspContext` 类。 其中一个重要的方法就是`removeArribute()`,它可接受一个或两个参数。比如,pageContext.removeArribute("attrName")移除四个 scope 中相关属性,但是下面这种方法只移除特定 scope 中的相关属性: ``` pageContext.removeAttribute("attrName", PAGE_SCOPE); ``` ### page 对象 这个对象就是页面实例的引用。它可以被看做是整个 JSP 页面的代表。 `page`对象就是`this`对象的同义词。 ### exception 对象 `exception`对象包装了从先前页面中抛出的异常信息。它通常被用来产生对出错条件的适当响应。 ## EL 表达式 EL 表达式是用`${}`括起来的脚本,用来更方便地读取对象。EL 表达式写在 JSP 的 HTML 代码中,而不能写在`<%`与`%>`引起的 JSP 脚本中。 JSP 表达式语言(EL)使得访问存储在 JavaBean 中的数据变得非常简单。JSP EL 既可以用来创建算术表达式也可以用来创建逻辑表达式。在 JSP EL 表达式内可以使用整型数,浮点数,字符串,常量 true、false,还有 null。 ### 一个简单的语法 典型的,当您需要在 JSP 标签中指定一个属性值时,只需要简单地使用字符串即可: ``` ``` JSP EL 允许您指定一个表达式来表示属性值。一个简单的表达式语法如下: ``` ${expr} ``` 其中,expr 指的是表达式。在 JSP EL 中通用的操作符是"."和"[]"。这两个操作符允许您通过内嵌的 JSP 对象访问各种各样的 JavaBean 属性。 举例来说,上面的 `` 标签可以使用表达式语言改写成如下形式: ``` ``` 当 JSP 编译器在属性中见到"\${}"格式后,它会产生代码来计算这个表达式,并且产生一个替代品来代替表达式的值。 您也可以在标签的模板文本中使用表达式语言。比如 `` 标签简单地将其主体中的文本插入到 JSP 输出中: ```

Hello JSP!

``` 现在,在标签主体中使用表达式,就像这样: ``` Box Perimeter is: ${2*box.width + 2*box.height} ``` 在 EL 表达式中可以使用圆括号来组织子表达式。比如 `${(1 + 2) _ 3}` 等于 9,但是 `${1 + (2 _ 3)}` 等于 7。 想要停用对 EL 表达式的评估的话,需要使用 page 指令将 isELIgnored 属性值设为 true: ``` <%@ page isELIgnored ="true|false" %> ``` 这样,EL 表达式就会被忽略。若设为 false,则容器将会计算 EL 表达式。 ### EL 中的基础操作符 EL 表达式支持大部分 Java 所提供的算术和逻辑操作符: | **操作符** | **描述** | | ---------- | ---------------------------------- | | . | 访问一个 Bean 属性或者一个映射条目 | | [] | 访问一个数组或者链表的元素 | | ( ) | 组织一个子表达式以改变优先级 | | + | 加 | | - | 减或负 | | \* | 乘 | | / or div | 除 | | % or mod | 取模 | | == or eq | 测试是否相等 | | != or ne | 测试是否不等 | | < or lt | 测试是否小于 | | > or gt | 测试是否大于 | | <= or le | 测试是否小于等于 | | >= or ge | 测试是否大于等于 | | && or and | 测试逻辑与 | | \|\| or or | 测试逻辑或 | | ! or not | 测试取反 | | empty | 测试是否空值 | ### JSP EL 中的函数 JSP EL 允许您在表达式中使用函数。这些函数必须被定义在自定义标签库中。函数的使用语法如下: ``` ${ns:func(param1, param2, ...)} ``` ns 指的是命名空间(namespace),func 指的是函数的名称,param1 指的是第一个参数,param2 指的是第二个参数,以此类推。比如,有函数 fn:length,在 JSTL 库中定义,可以像下面这样来获取一个字符串的长度: ``` ${fn:length("Get my length")} ``` 要使用任何标签库中的函数,您需要将这些库安装在服务器中,然后使用 `` 标签在 JSP 文件中包含这些库。 ### JSP EL 隐含对象 JSP EL 支持下表列出的隐含对象: | **隐含对象** | **描述** | | ---------------- | ------------------------------ | | pageScope | page 作用域 | | requestScope | request 作用域 | | sessionScope | session 作用域 | | applicationScope | application 作用域 | | param | Request 对象的参数,字符串 | | paramValues | Request 对象的参数,字符串集合 | | header | HTTP 信息头,字符串 | | headerValues | HTTP 信息头,字符串集合 | | initParam | 上下文初始化参数 | | cookie | Cookie 值 | | pageContext | 当前页面的 pageContext | 您可以在表达式中使用这些对象,就像使用变量一样。接下来会给出几个例子来更好的理解这个概念。 ### pageContext 对象 pageContext 对象是 JSP 中 pageContext 对象的引用。通过 pageContext 对象,您可以访问 request 对象。比如,访问 request 对象传入的查询字符串,就像这样: ``` ${pageContext.request.queryString} ``` ### Scope 对象 pageScope,requestScope,sessionScope,applicationScope 变量用来访问存储在各个作用域层次的变量。 举例来说,如果您需要显式访问在 applicationScope 层的 box 变量,可以这样来访问:applicationScope.box。 ### param 和 paramValues 对象 param 和 paramValues 对象用来访问参数值,通过使用 request.getParameter 方法和 request.getParameterValues 方法。 举例来说,访问一个名为 order 的参数,可以这样使用表达式:`${param.order}`,或者`${param["order"]}`。 接下来的例子表明了如何访问 request 中的 username 参数: ``` <%@ page import="java.io.*,java.util.*" %> <% String title = "Accessing Request Param"; %> <% out.print(title); %>

<% out.print(title); %>

${param["username"]}

``` param 对象返回单一的字符串,而 paramValues 对象则返回一个字符串数组。 ### header 和 headerValues 对象 header 和 headerValues 对象用来访问信息头,通过使用 request.getHeader 方法和 request.getHeaders 方法。 举例来说,要访问一个名为 user-agent 的信息头,可以这样使用表达式:`${header.user-agent}`,或者 `${header["user-agent"]}`。 接下来的例子表明了如何访问 user-agent 信息头: ``` <%@ page import="java.io.*,java.util.*" %> <% String title = "User Agent Example"; %>

<% out.print(title); %>

<% out.print(title); %>

${header["user-agent"]}

``` 运行结果如下: ![img](http://www.runoob.com/wp-content/uploads/2014/01/jsp-expression-language.jpg) header 对象返回单一值,而 headerValues 则返回一个字符串数组。 ## JSTL JSP 标准标签库(JSTL)是一个 JSP 标签集合,它封装了 JSP 应用的通用核心功能。 JSTL 支持通用的、结构化的任务,比如迭代,条件判断,XML 文档操作,国际化标签,SQL 标签。 除了这些,它还提供了一个框架来使用集成 JSTL 的自定义标签。 根据 JSTL 标签所提供的功能,可以将其分为 5 个类别。 - **核心标签** - **格式化标签** - **SQL 标签** - **XML 标签** - **JSTL 函数** ### JSTL 库安装 Apache Tomcat 安装 JSTL 库步骤如下: 从 Apache 的标准标签库中下载的二进包(jakarta-taglibs-standard-current.zip)。 - 官方下载地址: - 本站下载地址:[jakarta-taglibs-standard-1.1.2.zip](http://static.runoob.com/download/jakarta-taglibs-standard-1.1.2.tar.gz) 下载 **jakarta-taglibs-standard-1.1.2.zip** 包并解压,将 **jakarta-taglibs-standard-1.1.2/lib/** 下的两个 jar 文件:**standard.jar** 和 **jstl.jar** 文件拷贝到 **/WEB-INF/lib/** 下。 将 tld 下的需要引入的 tld 文件复制到 WEB-INF 目录下。 接下来我们在 web.xml 文件中添加以下配置: ``` http://java.sun.com/jsp/jstl/fmt /WEB-INF/fmt.tld http://java.sun.com/jsp/jstl/fmt-rt /WEB-INF/fmt-rt.tld http://java.sun.com/jsp/jstl/core /WEB-INF/c.tld http://java.sun.com/jsp/jstl/core-rt /WEB-INF/c-rt.tld http://java.sun.com/jsp/jstl/sql /WEB-INF/sql.tld http://java.sun.com/jsp/jstl/sql-rt /WEB-INF/sql-rt.tld http://java.sun.com/jsp/jstl/x /WEB-INF/x.tld http://java.sun.com/jsp/jstl/x-rt /WEB-INF/x-rt.tld ``` 使用任何库,你必须在每个 JSP 文件中的头部包含 **** 标签。 ### 核心标签 核心标签是最常用的 JSTL 标签。引用核心标签库的语法如下: ``` <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> ``` | 标签 | 描述 | | :---------------------------------------------------------------------- | :-------------------------------------------------------------------------- | | [``](http://www.runoob.com/jsp/jstl-core-out-tag.html) | 用于在 JSP 中显示数据,就像<%= ... > | | [``](http://www.runoob.com/jsp/jstl-core-set-tag.html) | 用于保存数据 | | [``](http://www.runoob.com/jsp/jstl-core-remove-tag.html) | 用于删除数据 | | [``](http://www.runoob.com/jsp/jstl-core-catch-tag.html) | 用来处理产生错误的异常状况,并且将错误信息储存起来 | | [``](http://www.runoob.com/jsp/jstl-core-if-tag.html) | 与我们在一般程序中用的 if 一样 | | [``](http://www.runoob.com/jsp/jstl-core-choose-tag.html) | 本身只当做和的父标签 | | [``](http://www.runoob.com/jsp/jstl-core-choose-tag.html) | 的子标签,用来判断条件是否成立 | | [``](http://www.runoob.com/jsp/jstl-core-choose-tag.html) | 的子标签,接在标签后,当标签判断为 false 时被执行 | | [``](http://www.runoob.com/jsp/jstl-core-import-tag.html) | 检索一个绝对或相对 URL,然后将其内容暴露给页面 | | [``](http://www.runoob.com/jsp/jstl-core-foreach-tag.html) | 基础迭代标签,接受多种集合类型 | | [``](http://www.runoob.com/jsp/jstl-core-foreach-tag.html) | 根据指定的分隔符来分隔内容并迭代输出 | | [`

``` 以上程序输出结果为: ``` Hello Custom Tag! ``` ### 访问标签体 你可以像标准标签库一样在标签中包含消息内容。如我们要在我们自定义的 Hello 中包含内容,格式如下: ``` This is message body ``` 我们可以修改标签处理类文件,代码如下: ```java package com.runoob; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import java.io.*; public class HelloTag extends SimpleTagSupport { StringWriter sw = new StringWriter(); public void doTag() throws JspException, IOException { getJspBody().invoke(sw); getJspContext().getOut().println(sw.toString()); } } ``` 接下来我们需要修改 TLD 文件,如下所示: ``` 1.0 2.0 Example TLD with Body Hello com.runoob.HelloTag scriptless ``` 现在我们可以在 JSP 使用修改后的标签,如下所示: ``` <%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%>

A sample custom tag This is message body

``` 以上程序输出结果如下所示: ``` This is message body ``` ### 自定义标签属性 你可以在自定义标准中设置各种属性,要接收属性,值自定义标签类必须实现 setter 方法, JavaBean 中的 setter 方法如下所示: ```java package com.runoob; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import java.io.*; public class HelloTag extends SimpleTagSupport { private String message; public void setMessage(String msg) { this.message = msg; } StringWriter sw = new StringWriter(); public void doTag() throws JspException, IOException { if (message != null) { /* 从属性中使用消息 */ JspWriter out = getJspContext().getOut(); out.println( message ); } else { /* 从内容体中使用消息 */ getJspBody().invoke(sw); getJspContext().getOut().println(sw.toString()); } } } ``` 属性的名称是"message",所以 setter 方法是的 setMessage()。现在让我们在 TLD 文件中使用的元素添加此属性: ``` 1.0 2.0 Example TLD with Body Hello com.runoob.HelloTag scriptless message ``` 现在我们就可以在 JSP 文件中使用 message 属性了,如下所示: ``` <%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%> A sample custom tag

``` 以上实例数据输出结果为: ``` This is custom tag ``` 你还可以包含以下属性: | 属性 | 描述 | | :---------- | :------------------------------------------------------- | | name | 定义属性的名称。每个标签的是属性名称必须是唯一的。 | | required | 指定属性是否是必须的或者可选的,如果设置为 false 为可选。 | | rtexprvalue | 声明在运行表达式时,标签属性是否有效。 | | type | 定义该属性的 Java 类类型 。默认指定为 **String** | | description | 描述信息 | | fragment | 如果声明了该属性,属性值将被视为一个 **JspFragment**。 | 以下是指定相关的属性实例: ``` ..... attribute_name false java.util.Date false ..... ``` 如果你使用了两个属性,修改 TLD 文件,如下所示: ``` ..... attribute_name1 false java.util.Boolean false attribute_name2 true java.util.Date ..... ```