43.1. Apusic JSP 开发

43.1.1. JSP概述

JavaServer Pages (JSP)技术允许开发人员轻松的创建静态或动态的Web内容。JSP不仅具有象Servlet一样创建动态Web页面的能力,而且更接近创建静态内容的方式。JSP使得页面的动态内容与它的表示进一步分离。JSP的设计迎合了两个不同的技术层面:页面的图形设计和创建动态内容的软件开发。JSP的主要特性包括:

  • JSP是基于文本的文档,用来处理客户端请求(request)和构造响应(response)

  • 构造server端访问的对象

  • 定义扩展JSP语言的机制

Apusic JSP建立在Sun Microsystem提出的JSP2.1规范之上,完全符合JSP2.1规范,同时兼容JSP2.0与JSP1.2规范。

43.1.1.1. 什么是JSP

JSP是以文本为基础的文档,它包含两种类型的文本:静态模板数据和JSP元素。

  • 静态模板数据:表达成文本格式内容,如HTML、XML等

  • JSP元素:用来构造动态内容

JSP页面定义了实现JSP页面语义的实现类。实现类是Servlet的子类,容器在用户访问JSP页面时自动转向到对应的实现类来处理用户的请求。

43.1.1.2. JSP如何处理请求

下面描述了一个典型的JSP请求是怎样被处理的:

1. 浏览器从服务器请求一个JSP页面(JSP页面文件以.jsp作为后缀)

2. Apusic服务器接受请求

3. JSP容器查找被请求的JSP文件,然后利用JSP编译器将该文件转换为一个实现了javax.servlet.jsp.JspPage接口的servlet类。jsp文件只有在需要时才会被编译;一般在第一次被请求或文件被修改后。这样,以前编译的JSP servlet类就可以被重复使用,使得以后的响应更快

4. 产生的JspPage servlet类被调用来处理浏览器请求

43.1.2. Apusic JSP变动及其升级

本章节主要介绍Apusic JSP部分跟随规范变动和升级的内容,具体开发内容的变动体现在开发指南部分

43.1.2.1. 从JSP2.0到JSP2.1的主要变动

43.1.2.1.1. JSP 2.1支持统一表达语言Unified Expression Language

在JSP2.0的表达式语言基础上,JSP2.1引入了统一表达式语言(Unified EL)。它是JSP2.0所提供的表达式语言与为JavaServer Faces技术而创的表达式语言的结合体。

JSP2.0中的表达式语言允许网页设计者使用简单的表达式来动态读取JavaBean的数据。JSP支持简单的请求(request)/响应(response)生命周期。在此周期中,当页面被执行时,HTML标记会被即时生成。因此,JSP2.0所提供的简洁、只读的表达式语言非常适合JSP应用。

另一方面,JavaServer Faces技术提供了一个多阶段的生命周期来支持其精密的用户界面组件模型。此模型允许转换与校验组件数据,把组件数据传递到对象,以及处理组件事件。为了支持这些功能,JavaServer Faces技术所使用的表达式语言需要提供以下功能:

  • 表达式的延迟演算

  • 允许对数据赋值

  • 允许调用方法

合并这两种表达式语言有两个主要原因:第一,网页开发者就可以自由地混合JSP与JavaServer Faces标签,而不需要担心两种技术由于生命周期不同而造成冲突。第二,令其他基于JSP的技术也能运用JSF所使用的新技术。虽然标准JSP标签库与静态内容仍旧只能使用JSP2.0中的技术,但JSP自定义标签开发人员在开发新标签时则可以从Unified EL的新特性中得益。

43.1.2.2. 从JSP1.2到JSP2.0的主要变动

43.1.2.2.1. JDK要求

JSP 1.2可以在Java 2标准版1.3版本运行,而JSP 2.0要求使用Java 2标准版1.4或更新版本,JSP 2.0使用由Servlet 2.4规定的Web程序部署描述格式。

43.1.2.2.2. JSP 2.0支持表达语言expression language

JSP 2.0支持表达语言(expression language)。JSTL表达式语言可以使用标记格式方便地访问JSP的隐含对象和JavaBeans组件,JSTL的核心标记提供了流程和循环控制功能。自制标记也有自定义函数的功能,因此基本上所有seriptlet能实现的功能都可以由JSP替代。请参考:第 43.1.3.5 节 “表达式语言”

43.1.2.2.3. JSP 2.0中加入了JSP fragment

JSP 2.0中加入了JSP fragment,它的基本特点是可以使处理JSP的容器推迟评估JSP标记属性。一般JSP是首先评估JSP标记的属性,然后在处理JSP标记时使用这些属性,而JSP fragment提供了动态的属性。

43.1.2.2.4. JSP 2.0中加入了SimpleTag

JSP 2.0中加入了新的Tag处理方法(javax.servlet.jsp.tagext.SimpleTag),它定义了用来实现简单标记的接口。SimpleTag接口不使用doStartTag()和doEndTag()方法,而提供了一个简单的doTag()方法。需要在一个自制标记中实现的所有逻辑过程、循环和对标记体的评测等都在这个方法中实现。

43.1.3. Apusic JSP开发指南

43.1.3.1. JSP页面的生命周期

JSP象Servlet一样处理客户端的请求(request)。因此,JSP页面的生命周期和许多功能都决定于Servlet技术。关于Servlet的讨论请参考第 43.2 节 “Apusic Http Servlets 开发”

当一个请求(request)映射到JSP页面时,请求(request)首先被特殊的Servlet处理,检查JSP页面和它对应的实现类。如果发现实现类比JSP页面旧,那么就把JSP页面转化成一个servlet类并编译。在这个过程中,JSP比Servlet具有优势的一个地方是编译是自动进行的。

在转化阶段,对JSP页面中每一种类型的数据处理都不一样。模板数据被转化成代码然后写入返回给客户端的输出流中。JSP元素被作如下处理:

如果一个JSP页面命名为test,那么JSP的实现类的源文件就保存在:

APUSIC_HOME/domains/<domain_name>/deploy/<webapp_name>/tmpfiles/jsp/_jspx_test__jsp.java

转化和编译阶段都可能产生错误,但只有在第一次访问页面时才被发现。如果错误发生在页面转化过程中,服务器将抛出ParseException异常,并且Servlet源文件为空或不完整。如果错误发生在页面的编译期,服务器会抛出JasperException异常和错误所在的Servlet源文件的位置。一旦JSP被转化和编译,JSP页面的实现类基本上和Servlet的声明周期相同。请参考第 43.2.3.1 节 “Servlet生命周期”

  • 如果JSP页面的实现类不存在,那么容器:

    1. 转载实现类

    2. 实例化

    3. 调用jspInit方法初始化

  • 调用_jspService方法,处理请求(request)和响应(response)

  • 如果容器需要删除JSP页面的实现类,调用jspDestroy方法

43.1.3.2. 初始化和结束一个JSP页面

开发人员能够通过覆盖JspPage接口的jspInit方法来定制JSP页面的初始化过程,允许它读取持久性配置文件、初始化资源和执行任何一次性的动作。开发人员可以调用jspDestroy释放资源。在JSP页面中定义方法,请参考第 43.1.3.4.3.3 节 “脚本元素 (Scripting Elements)”

43.1.3.3. 创建静态内容

开发人员可以象创建普通页面一样简单的在JSP页面中创建静态内容。静态内容表现为文本格式,如HTML、WML和XML,缺省的格式是HTML。

43.1.3.4. 创建动态内容

开发人员可以通过在JSP元素中访问Java对象来创建动态内容。

43.1.3.4.1. 使用内置对象

在JSP页面中可以访问不同的对象,包括EJB、JavaBeans等。JSP技术使一些对象自动可用,开发人员也可以创建与应用相关的对象。内置对象是由 Web容器创建的、包含了与请求(request)响应(response)和应用相关信息的对象,大部分的内置对象都在 Java Servlet技术规范中定义。JSP页面的作者能够访问确定的内置对象,从页面的开始这些内置对象都是可用的,可以在脚本元素(Scripting Elements)中通过脚本变量访问。使用页面声明标签(<%! %>)定义的方法无法直接使用内置对象,需要通过参数传入

每一个内置对象都对应核心 Java API或 Java Servlet API 的类或接口。

变量名类型描述
requestjavax.servlet.ServletRequest的子类,如javax.servlet.http.HttpServletRequestrequest触发了 JSP页面的执行。作用范围:request。
responsejavax.servlet.ServletResponse的子类,如javax.servlet.http.HttpServletResponse返回给客户端的响应(response)。在JSP页面中不常使用。作用范围:page
pageContextjavax.servlet.jsp.PageContextJSP页面的执行环境。提供了管理不同作用范围属性的API,在扩展标记中被大量使用。作用范围:page
sessionjavax.servlet.http.HttpSession为客户端创建的 session对象。作用范围:session
applicationjavax.servlet.ServletContext在同一个Web应用中的Servlet 和其他Web组件的运行环境。从ServletConfig对象获得。作用范围:application
outjavax.servlet.jsp.JspWriter输出流。作用范围:page
configjavax.servlet.ServletConfigJSP页面从 ServletConfig对象获得初始化信息。作用范围:page
pagejava.lang.ObjectJSP页面实现类处理当前请求的实例。等同于“this”。作用范围:page

“作用范围”的概念在下一节介绍。

43.1.3.4.2. 对象的作用范围

当开发人员在JSP页面中实例化一个对象,可能希望它可以被Web应用中的其他对象访问。为了控制对象的可访问性,JSP规范定义了一系列作用范围对象,在其中可以放置对其他对象的引用(reference)。这些作用范围是:page、request、session和application。在运行过程中,作用范围被相应的Java对象实现。

作用范围对象类型描述
pagejavax.servlet.jsp.PageContext作用范围为page的对象只能在创建它的当前页面被访问。当响应(response)返回给客户端或请求被转向其他地方时,所有对该对象的引用都将释放。作用范围为page的对象其引用(reference)存储在PageContext对象中。
requestjavax.servlet.ServletRequest作用范围为request的对象可以在处理同一请求(request)的JSP页面中被访问。请求(request)处理结束后,所有对该对象的引用都将释放。如果请求(request)在同一运行时间被转移给其他Web资源,对象仍然可访问。作用范围为request的对象其引用(reference)存储在request对象中。
sessionjavax.servlet.http.HttpSession作用范围为session的对象可以在同一session的JSP页面中被访问。当session结束后,所有对该对象的引用都将释放。作用范围为session的对象其引用(reference)存储在session对象中。
applicationjavax.servlet.ServletContext作用范围为application的对象可以在同一Web应用的JSP页面中被访问,对象的引用(reference)存储在application对象中。当运行环境收回ServletContext时,所有存储在application对象中对象引用(reference)都将被释放。

使用useBean动作时可以定义对象的作用范围,选择一个范围属性来确定JavaBeans实例在什么范围可用,如:

<jsp:useBean id="myCart" scope="session" class="Cart">

范围属性的实现对象在JSP页面中自动可用,表现为脚本变量,在脚本元素中使用。这些脚本变量和范围属性使用同样的名字:page、request、session和application。例如下面的代码片断使用了内置的request对象。因为使用了session变量来存储Cart对象,那么它可以被同一session作用范围的其他JSP页面访问。

<%
CartLineItem lineItem = new CartLineItem();
lineItem.setID(request.getParameter("cdId"));
lineItem.setCDTitle(request.getParameter("cdTitle"));
lineItem.setPrice(request.getParameter("cdPrice"));
myCart.lineItems.addElement(lineItem);
session.putValue("myLineItems", myCart.getLineItems());
%>
[注意]注意

缺省情况下,JSP页面可以访问session作用范围。但如果页面的伪指令page设置session的属性为false,那么页面将不能访问当前的Http session,而且也不能使用session内置对象。

例如,当页面包含下面的代码,前面的useBean动作和脚本片段都将非法:

<%@ page session="false" %>
43.1.3.4.3. JSP元素(Element)

JSP包含模板数据(template data)和元素(elements)。元素能被Web容器识别,提供了创建动态内容的能力。模板数据不需要识别,例如HTML和XML代码,直接被返回到客户端。模板数据通常用来产生静态内容和格式化动态内容。JSP元素分为三个类别:伪指令元素(Directive Elements)、动作元素(Action Elements)和脚本元素(Scripting Elements)。

JSP页面结构图

43.1.3.4.3.1. 伪指令元素 (Directive Elements)

伪指令提供了跟任何请求(request)无关的、关于JSP页面的全局声明信息。例如可以在页面引入包(import package),也可以指示页面关联当前的Http Session。伪指令不能向响应(response)中输出信息,它只是为JSP页面转化成相应Servlet的转化阶段提供信息。伪指令的语法:

<%@ directive { attr=”value” }* %>

例如,下面的伪指令引入了java.util包和关联JSP页面到当前的Http Session。

<%@ page import="java.util.*" session="true"%>

JSP规范定义了三种伪指令:page、include和taglib。

伪指令描述语法
include包含其他文件的内容<%@ include file=" relativeURL "%>
page定义JSP页面的属性

<%@ page page_directive_attr_list %>

page_directive_attr_list ::= {language="scriptingLanguage"}

{extends="className" }

{ import="importList" }

{ session="true|false" }

{buffer="none|sizekb" }

{autoFlush="true|false" }

{isThreadSafe="true|false" }

{ info="info_text"}

{ errorPage="error_url" }

{isErrorPage="true|false" }

{contentType="ctinfo" }

{pageEncoding="peinfo" }

tablib为自定义标记设置标记库和前缀。<%@ taglib uri=" URI " prefix=" tagPrefix"%>
43.1.3.4.3.2. 动作元素 (Action Elements)

动作元素可以影响当前的输出和使用、改变、创建对象。动作元素提供了处理请求(request)阶段的信息。动作元素可以是标准的,定义在JSP规范中;也可以是客户自定义的,请参考第 43.3 节 “JSP扩展标记”。动作元素遵循XML的语法。例如,jsp:include动作可以插入JSP页面到当前的页面:

<jsp:include page="header.jsp" flush="true"/>

jsp:useBean动作可以创建JavaBean对象:

<jsp:useBean id="cBean" scope="application" class="Expns.CBean">
<%
cBean.getConnected();
cBean.getEngine();
%>
</jsp:useBean>

下面列出了JSP规范定义的标准动作 。

动作元素描述语法
<jsp:forward>传递请求(request)到其他Web资源

<jsp:forward page=”relativeURLspec”/>

<jsp:forwardpage=”urlSpec”>

{ <jsp:param .... />}*

</jsp:forward>

<jsp:getProperty>插入JavaBeans的属性值到结果中<jsp: getProperty name=" beanInstanceName "property=" propertyName "/>
<jsp:include>包含静态文件或Web组件的执行结果

<jsp:include page=”urlSpec”flush="true|false"/>

<jsp:include page="urlSpec"flush="true|false">

{ <jsp:param ..../> }*

</jsp:include>

<jsp:plugin>引起applet或bean的执行

<jsp:plugintype="bean|applet"

code="objectCode"

codebase="objectCodebase"

{align="alignment" }

{ archive="archiveList"}

{ height="height" }

{hspace="hspace" }

{ jreversion="jreversion"}

{ name="componentName" }

{vspace="vspace" }

{ width="width" }

{ nspluginurl="url" }

{iepluginurl="url" } >

{<jsp:params>

{ <jsp:paramname="paramName" value=”paramValue" /> }+

</jsp:params> }

{<jsp:fallback> arbitrary_text </jsp:fallback>}

</jsp:plugin>

<jsp:setProperty>设置JavaBeans的属性

<jsp: setProperty name=" beanInstanceName"

{ property="*" |

property="propertyName " [ param=" parameterName "]|

property=" propertyName " value="{ string | <%=expression

%>}" }

/>

<jsp:useBean>定位或实例化JavaBeans,指定名字和作用范围。

<jsp: useBean id=" beanInstanceName "

scope=" page |request| session| application"

{

class=" package. class " [ type="package. class "] |

beanName="{ package. class| <%= expression %>}"

type=" package.class "|

type=" package. class "

}

{/> | > other elements

</ jsp: useBean> }

<jsp:param>提供 键/值信息<jsp:param name="name" value="value" />
<jsp:params>是<jsp:plugin>的一部分 
<jsp:fallback>是<jsp:plugin>的一部分 
43.1.3.4.3.3. 脚本元素 (Scripting Elements)

脚本元素使开发人员能够在JSP页面中嵌入Java代码。脚本元素通常用来维护对象,也可以通过执行计算来影响内容的产生。有三种类型的脚本元素:声明(declarations)、脚本(scriptlets)和表达式(expressions)。

声明(declarations)用来在JSP页面中声明变量和方法。声明不会产生任何输出,在JSP页面初始化时被初始化。JSP页面的回调方法jspInit()与jspDestroy()应在此定义。例子:

<%! int i; %>
<%! int i = 0; %>
<%! public String f(int i) { if (i<3) return(“...”); ... } %>

语法:

<%! declaration(s) %>

脚本(scriptlets)允许开发人员嵌入任何有效的Java代码。可以使用在声明中定义的变量和方法。脚本在请求(request)的时刻执行。一个简单的例子,产生日期和时间:

<% if (Calendar.getInstance().get(Calendar.AM_PM) == Calendar.AM) {%>
Good Morning
<% } else { %>
Good Afternoon
<% } %>

在脚本中同样能够使用本地变量:

<% int i; i= 0; %>
Hi, the value of i is <% i++ %>

语法:

<% scriptlet %>

表达式(expressions)使开发人员能够在页面中嵌入任何有效的Java表达式。在请求(request)时刻Web容器计算表达式的值并转换结果为字符串(String),然后把结果字符串写入HttpResponse对象。例如插入当前日期:

<%= (new java.util.Date()).toLocaleString() %>

语法:

<%= expression %>

43.1.3.5. 表达式语言

JSP2.0的一个首要特点就是表达式语言,表达式语言能使方便地访问JavaBeans组件成为可能。例如,表达式语言能使用简单的语法${name},${name.foo.bar} ,访问对象和对象内部属性。

举例:test属性的值为session-scoped范围内cart对象中numberOfItems属性值是否大于0

<c:if test="${sessionScope.cart.numberOfItems > 0}">
  ...
</c:if>
<c:if test="${sessionScope.cart.numberOfItems > 0}">
  ...
</c:if>

注意:表达式语言中的属性与脚本(Scriptlets)中的变量并不互通。若要在脚本(Scriptlets)中访问表达式语言中的属性,需要使用相应scope的getAttribute()方法访问;若要在表达式语言中使用脚本中的变量,则需要在脚本中使用相应scope(例如page)的setAttribute()方法设置属性

43.1.3.5.1. 使表达式语言失效

在JSP2.0之前,因为--${}--不是保留的关键字和符号,在以前的系统中,可能存在使用了该符号。为了保持向前兼容的功能,可以使表达式语言失效,语法如下:

<%@ page isELIgnored ="true|false" %>

属性为true时,表达式语言失效,属性为false时,表达式语言生效,系统默认是false。

43.1.3.5.2. 使用表达式语言

表达式语言能使用在

  • 静态文字

  • 任何能够接受表达式语言的标签属性,包括标准或定制的标签。

三种方式设定标签属性值

  • 简单表达式 ,<some:tag value="${expr}"/>,属性值被强制转换成属性值期望的类型。

  • 有一个或多个表达式,且有文字夹杂,<some:tag value="some${expr}${expr}text${expr}"/>,这种情况先转换成字符串,然后被强制转换成属性值期望的类型。

  • 直接赋值,<some:tag value="sometext"/>。

表达式通常根据期望类型的上下文来设定标签属性值,当不能准确匹配时,通常会进行强制转换。例如:${1.2E4 + 1.4}给一个float标签赋值时,会通过以下转换:

Float.valueOf("1.2E4 + 1.4").floatValue()
43.1.3.5.3. 变量

web容器寻找表达式中出现的变量时,根据page, request, session,application范围和次序来寻找变量,当变量名为系统对象时,返回系统对象。

主要系统对象:

  • pageContext:可提供访问servletContext,session,request,response等对象。

  • 其它一些对象:

名称解释
param将请求参数名称映射到单个字符串参数值(通过调用 ServletRequest.getParameter(String name) 获得)。getParameter (String) 方法返回带有特定名称的参数。表达式$(param.name) 相当于 request.getParameter (name)。
paramValues将请求参数名称映射到一个数值数组(通过调用 ServletRequest.getParameter(String name) 获得)。它与 param 隐式对象非常类似,但它检索一个字符串数组而不是单个值。表达式${paramvalues.name) 相当于request.getParamterValues(name)。
header将请求头名称映射到单个字符串头值(通过调用 ServletRequest.getHeader(Stringname) 获得)。表达式 ${header.name} 相当于request.getHeader(name)。
headerValues将请求头名称映射到一个数值数组(通过调用 ServletRequest.getHeaders(String)获得)。它与头隐式对象非常类似。表达式 ${headerValues.name} 相当于request.getHeaderValues(name)。
cookie将 cookie 名称映射到单个 cookie 对象。向服务器发出的客户端请求可以获得一个或多个cookie。表达式 ${cookie.name.value} 返回带有特定名称的第一个 cookie值。如果请求包含多个同名的 cookie,则应该使用 ${headerValues.name} 表达式。
initParam将上下文初始化参数名称映射到单个值(通过调用ServletContext.getInitparameter(String name) 获得)。
43.1.3.5.4. 文字

JSP 表达式语言定义可在表达式中使用的以下文字:

文字文字的值
Booleantrue 和 false
Integer与 Java 类似。可以包含任何正数或负数,例如 24、-45、567
Floating Point与 Java 类似。可以包含任何正的或负的浮点数,例如 -1.8E-45、4.567
String任何由单引号或双引号限定的字符串。对于单引号、双引号和反斜杠,使用反斜杠字符作为转义序列。必须注意,如果在字符串两端使用双引号,则单引号不需要转义。
Nullnull
43.1.3.5.5. 操作符
类型操作符
算术型+、-(二元)、*、/、div、%、mod、-(一元)
逻辑型and、&&、or、||、!、not
关系型==、eq、!=、ne、、gt、<=、le、>=、ge。可以与其他值进行比较,或与布尔型、字符串型、整型或浮点型文字进行比较。
空操作符是前缀操作,可用于确定值是否为空。
条件型A ?B :C。根据 A 赋值的结果来赋值 B 或 C。
43.1.3.5.6. 保留关键字

这些关键字不一定现在就已经用到,但是将来可能用到

and    eq   gt   true   instanceof
or    ne   le   false  empty
not   lt   ge   null   div   mod
43.1.3.5.7. 举例列表
表达式结果
${1 > (4/2)}false
${4.0 >= 3}true
${100.0 == 100}true
${(10*10) ne 100}false
${'a' < 'b'} true ${'hip' gt 'hit'}false
${4 > 3}true
${1.2E4 + 1.4}12001.4
${3 div 4}0.75
${10 mod 4}2
${!empty param.Add}当request中Add的属性值为空字串或null时返回真
${pageContext.request.contextPath}The context path
${sessionScope.cart.numberOfItems}The value of the numberOfItems property of the session-scoped attribute named cart
${param['mycom.productId']}返回request中mycom.productId的属性值
${header["host"]}The host
${departments[deptName]}departments map中的deptName键值
${requestScope['javax.servlet. forward.servlet_path']}The value of the request-scoped attribute named javax.servlet. forward.servlet_path

43.1.3.6. 使用JavaBeans

JavaBeans组件是Java的类,能够很容易的重用和组装在一起形成应用。任何Java类只要遵循一定的设计惯例就可能成为JavaBeans组件。JSP技术通过JSP元素支持JavaBeans组件,可以创建和初始化beans,设置和得到属性。本节提供了JavaBeans组件的基本信息和在JSP页面中访问JavaBeans组件。

43.1.3.6.1. JavaBeans 设计惯例

JavaBeans的设计惯例约定了类的属性和访问属性的public方法的定义方式。JavaBeans的属性能够:

  • 读 / 写、只读、只写

  • 包含单值或数组

属性不一定要通过实例变量被实现,但属性必须能够通过pubilc方法访问。对public方法的要求是:

  • 对应每个可读的属性,必须有方法PropertyClass getProperty() { ... }得到属性

  • 对应每个可写的属性,必须有方法setProperty(PropertyClass pc) { ... }设置属性

除了属性方法,JavaBeans组件还必须具有无参数的公共构造函数。下面是一个简单的JavaBeans范例程序:

public class Currency {
   private Locale locale;
   private double amount;
   public Currency() {
      locale = null;
      amount = 0.0;
   }
   public void setLocale(Locale l) {
      locale = l;
   }
   public void setAmount(double a) {
      amount = a;
   }
   public String getFormat() {
      NumberFormat nf =
         NumberFormat.getCurrencyInstance(locale);
      return nf.format(amount);
   }
}
43.1.3.6.2. 创建和使用JavaBeans

在JSP页面中使用jsp:useBean标记声明JavaBeans,形式如下:

<jsp:useBean id="beanName"
   class="fully_qualified_classname" scope="scope"/>

jsp:userBean标记声明页面将使用JavaBeans,并设置JavaBeans的作用范围:application、session、request和page。如果bean不存在,那么声明将创建bean然后把它存储在属性中设置的作用范围对象中。id属性决定了bean的名字,作为在JSP页面中引用bean对象的标识符。

43.1.3.6.3. 设置JavaBeans的属性

可以通过两种方式设置JavaBeans的属性:使用jsp:setProperty标记或者使用脚本,

<% beanName.setPropName(value); %>

jsp:setProperty的语法依赖于属性值的来源,下面总结了使用 jsp:setProperty 设置 JavaBeans属性的不同方式:

属性值的来源语法
String常量<jsp:setProperty name="beanName" property="propName" value="string constant"/>
Request参数<jsp:setProperty name="beanName" property="propName" param="paramName"/>
Request参数名匹配bean属性

<jsp:setProperty name="beanName" property="propName"/>

<jsp:setProperty name="beanName" property="*"/>

表达式<jsp:setProperty name="beanName" property="propName" value="<%= expression %>"/>
[注意]注意
  • beanName必须和useBean标记中的id属性值相同

  • JavaBeans组件中必须有setPropName方法

  • paramName必须是请求(request)参数名

下面的代码范例声明了前面定义的JavaBeans,然后设置它的属性:

<jsp:useBean id="currency" class="util.Currency"
   scope="session">
   <jsp:setProperty name="currency" property="locale"
      value="<%= request.getLocale() %>"/>
</jsp:useBean>
<jsp:setProperty name="currency" property="amount"
   value="<%=cart.getTotal()%>"/>

属性可以设置为字符串(String)常量或请求(request)参数。由于这两种类型都是字符串(String),Web容器会自动的转换字符串(String)为正确的属性类型。下表列出了字符串如何转换为目标类型。

目标类型转换
Bean属性setAsText(string-literal)
boolean或Booleanjava.lang.Boolean.valueOf(String)
byte或Bytejava.lang.Byte.valueOf(String)
char或Characterjava.lang.String.charAt(0)
double或Doublejava.lang.Double.valueOf(String)
int或Integerjava.lang.Integer.valueOf(String)
float或Floatjava.lang.Float.valueOf(String)
long或Longjava.lang.Long.valueOf(String)
short或Shortjava.lang.Short.valueOf(String)
ObjectString(string-literal)
43.1.3.6.4. 得到JavaBeans 的属性

可以通过几种方式获得JavaBeans组件的属性值。其中两种方式(jsp:getProperty标记和表达式)是转化属性值为String然后输出属性值到当前的内置对象out :

  • <jsp:getProperty name="beanName" property="propName"/>

  • <%= beanName.getPropName() %>

对于这两种方法,beanName必须和useBean标记中的id属性值相同,而且JavaBeans中必须定义了getPropName方法。

如果需要获得属性值但并不转化它,也不把它输出到内置对象out,那么必须使用脚本,例如:

<% Object o = beanName.getPropName(); %>

下面的范例代码展示了如何获得前面声明的JavaBeans的属性值,

<jsp:getProperty name="currency" property="format"/>

或,

<%= currency.getFormat() %>

43.1.3.7. 在JSP页面中包含其他内容

在JSP页面中包含其他Web资源有两种方式:使用include伪指令和<jsp:include>动作。include伪指令是在JSP页面转化到对应的servlet的过程中被处理的,它的效果就是在JSP页面中插入另外一个文件的文本内容,不管文件是静态内容还是JSP页面。一般使用include伪指令包含banner内容和版权(copyright)信息。include伪指令的语法是:

<%@ include file="filename" %>

<jsp:include>动作是在JSP页面的执行过程中被处理的。<jsp:include>动作允许在JSP页面中包含静态或者动态的资源,而包含静态和动态资源的结果十分不同。如果资源是静态的,那么它的内容被插入到包含它的JSP页面中;如果资源是动态的,那么首先把请求(request)传递给它,然后执行,最后把执行结果插入到包含它的JSP页面中。<jsp:include>动作的语法是:

<jsp:include page="includedPage" />
include 机制描述语法
include伪指令不管是静态还是动态资源,都是插入文件的文本内容<%@ include file="filename" %>
<jsp:include>动作
  • 静态资源,插入文件的文本内容

  • 动态资源,插入JSP页面的执行结果

<jsp:include page="includedPage" />

43.1.3.8. 传递控制到其他Web组件

从JSP页面传递控制到其他Web组件的方法是使用Java Servlet API,详细的描述请参考第 43.2.4.8.2 节 “传递控制给其他Web组件”。在 JSP 页面中使用jsp:forward动作可以达到传递控制的目的,例如:

<jsp:forward page="/main.jsp" />

43.1.3.9. 在JSP页面中包含Applet

可以使用jsp:plugin元素在JSP页面中包含applet或JavaBeans组件。jsp:plugin产生适当的依赖于客户端浏览器HTML代码(<object>或<embed>),如果有必要,则会下载Java插件和客户端组件并执行。<jsp:plugin>标记被<object>或<embed>标记代替,<jsp:plugin>的属性标记提供了配置信息。<jsp:param>标记指出了applet或JavaBeans的参数,<jsp:fallback>标记指出了当applet或JavaBeans不被支持时客户端显示的内容。下面是一个在JSP页面中包含applet的例子:

<jsp:plugin type=applet code=”Molecule.class” codebase=”/html” >
    <jsp:params>
      <jsp:param
        name=”molecule”
        value=”molecules/benzene.mol”/>
    </jsp:params>
    <jsp:fallback>
      <p> unable to start plugin </p>
    </jsp:fallback>
</jsp:plugin>

jsp:plugin标记的语法是:

<jsp:plugin
   type="bean|applet"
   code="objectCode"
   codebase="objectCodebase"
   { align="alignment" }
   { archive="archiveList" }
   { height="height" }
   { hspace="hspace" }
   { jreversion="jreversion" }
   { name="componentName" }
   { vspace="vspace" }
   { width="width" }
   { nspluginurl="url" }
   { iepluginurl="url" } >
   { <jsp:params>
      { <jsp:param name="paramName" value="paramValue" /> }+
   </jsp:params> }
   { <jsp:fallback> arbitrary_text </jsp:fallback> }
</jsp:plugin>

43.1.3.10. 使用Apusic JSP预编译

Apusic的JSP编译器会自动的处理JSP页面,所以通常不需要直接使用JSP编译器。但是在一些特殊的情况下,直接使用Apusic的JSP编译器对JSP源文件进行预编译会非常有用。Apusic提供了jspc工具对JSP文件进行预编译,它的工作原理是首先对JSP源文件进行解析生成java文件,然后使用标准的Java编译器编译。

详情请参考第 41.6 节 “JSPC工具”

对JSP进行预编译处理后可以按照正常的步骤部署Web应用