动作指令与编译指令不同,编译指令是通知 Servlet 引擎的处理消息,而动作指令只是运行时的动作。编译指令在将 JSP 编译成 Servlet 时起作用;而处理指令通常可替换成 JSP 脚本,它只是 JSP 脚本的标准化写法。
JSP 动作指令主要有如下7个。
jsp:forward:执行页面转向,将请求的处理转发到下一个页面。
jsp:param:用于传递参数,必须与其他支持参数的标签一起使用。
jsp:include:用于动态引入一个 JSP 页面。
jsp:plugin:用于下载 JavaBean 或 Applet 到客户端执行。
jsp:useBean:创建一个 JavaBean 的实例。
jsp:setProperty: 设置 JavaBean 实例的属性值。
jsp:getProperty:输出 JavaBean 实例的属性值。
forward 指令
forward 指令用于将页面响应转发到另外的页面。既可以转发到静态的 HTML 页面,也可以转发到动态的 JSP 页面,或者转发到容器中的 Servlet。
JSP 的 forward 指令的格式如下。
对于 JSP 1.0,使用如下语法:
<jsp:foeward page="{relativeURL | <%=expression%>}"/>
对于 JSP 1.1 以上规范,可使用如下语法:
<jsp:foeward page="{relativeURL | <%=expression%>}">
{<jsp:param.../>}
</jsp:foeward>
第二种语法用于在转发时增加额外的请求参数。增加的请求参数的值可以通过 HttpServletRequest 类的 getParameter()方法获取。
下面示例页面使用了 forward 动作指令来转发用户请求。
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage=""%>
<!DOCTYPE html>
<html>
<head>
<title> forward的原始页 </title>
</head>
<body>
<h3>forward的原始页</h3>
<jsp:forward page="forward-result.jsp">
<jsp:param name="age" value="29"/>
</jsp:forward>
</body>
</html>
这个 JSP 页面非常简单,它包含了简单的 title 信息,页面中也包含了简单的文本内容,页面的代码则将客户端请求转发到 forward-result.jsp 页面,转发请求时增加了一个请求参数:参数名为age,参数值为 29。
在 forward-result.jsp 页面中,使用 request 内置对象(request 内置对象是 HttpServletRequest 的实例,关于 request 的详细信息参看下一篇)来获取增加的请求参数值。
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage=""%>
<!DOCTYPE html>
<html>
<head>
<title> forward结果页 </title>
</head>
<body>
<!-- 使用request内置对象获取age参数的值 -->
<%=request.getParameter("age")%>
</body>
</html>
forward-result.jsp 页面中的第 9 行代码设置了 title 信息,并输出了 age 请求参数的值,在浏览器中访问 jsp-forward.jsp 页面的执行效果如下图所示。
从上图中可以看出,执行 forward 指令时,用户请求的地址依然没有发生改变,但页面内容却完全变为被 forward 目标页的内容。
执行 forward 指令转发请求时,客户端的请求参数不会丢失。看下面表单提交页面的例子,该页面没有任何动态的内容,只是一个静态的表单页,作用是将请求参数提交到 jsp-forward.jsp 页面。
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage=""%>
<!DOCTYPE html>
<html>
<head>
<title> 提交 </title>
</head>
<body>
<!-- 表单提交页面 -->
<form id="login" method="post" action="jsp-forward.jsp">
<input type="text" name="username">
<input type="submit" value="login">
</form>
</body>
</html>
修改 forward-result.jsp 页,增加输出表单参数的代码,也就是在 forward-result.jsp 页面上增加如下代码:
<!-- 输出 username 请求参数的值 -->
<%=request.getParameter("username")%>
在表单提交页面中的文本框中输入任意字符串后提交该表单,即可看到如下图所示的执行效果。
从上图中可看到,forward-result.jsp 页面中不仅可以输出 forward 指令增加的请求参数,还可以看到表单里 username 表单域对应的请求参数,这表明执行 forward 时不会丢失请求参数。
include 指令
include 指令是一个动态 include 指令,也用于包含某个页面,它不会导入被 include 页面的编译指令,仅仅将被导入页面的 body 内容插入本页面。
下面是 include 动作指令的语法格式:
<jsp:include page="{relativeURL | <%=expression%>}" flush="true"/>
或者
<jsp:include page="{relativeURL | <%=expression%>}" flush="true">
<jsp:param name="parameterName" value="patameterValue"/>
</jsp:include>
flush 属性用于指定输出缓存是否转移到被导入文件中。如果指定为 true,则包含在被导入文件中;如果指定为 false,则包含在原文件中。对于 JSP 1.1 以前版本,只能设置为 false。
对于第二种语法格式,则可在被导入页面中加入额外的请求参数。
下面的页面使用了动态导入语法来导入指定 JSP 页面。
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage=""%>
<!DOCTYPE html>
<html>
<head>
<title> jsp-include 测试 </title>
</head>
<body>
<!-- 使用动态 include 指令导入页面 -->
<jsp:include page="scriptlet.jsp" />
</body>
</html>
以上页面中<jsp:include.../>使用了动态导入语法来导入了 scriptlet.jsp。表面上看,该页面的执行效果与使用静态 include 导入的页面并没有什么不同。但查看 jsp-include.jsp 页面生成 Servlet 的源代码,可以看到如下片段:
// 使用页面输出流,生成 HTML 标签内容
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("<!-- 使用动态 include 指令导入页面 -->\r\n");
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "scriptlet.jsp", out, false);
out.write("\r\n");
out.write("</body>\r\n");
以上代码片段中显示了动态导入的关键:动态导入只是使用一个 include 方法来插入目标页面的内容,而不是将目标页面完全融入本页面中。
归纳起来,静态导入和动态导入有如下三点区别:
➢ 静态导入是将被导入页面的代码完全融入,两个页面融合成一个整体 Servlet;而动态导入则在 Servlet 中使用 include 方法来引入被导入页面的内容。
➢ 静态导入时被导入页面的编译指令会起作用;而动态导入时被导入页面的编译指令则失去作用,只是插入被导入页面的 body 内容。
➢ 动态包含还可以增加额外的参数。
除此之外,执行 include 动态指令时,还可增加额外的请求参数,如下面 JSP 页面所示。
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage=""%>
<!DOCTYPE html>
<html>
<head>
<title> jsp-include 测试 </title>
</head>
<body>
<jsp:include page="forward-result.jsp">
<jsp:param name="age" value="32"/>
</jsp:include>
</body>
</html>
在上面的 JSP 页面中的代码同样使用<jsp:include.../>指令包含页面,而且在 jsp:include 指令中还使用 param 指令传入参数,该参数可以在 forward-result.jsp 页面中使用 request 对象获取。
forward-result.jsp 前面已经给出,此处不再赘述。页面执行的效果如下图所示。
useBean、setProperty、getProperty 指令
这三个指令都是与 JavaBean 相关的指令,其中 useBean 指令用于在 JSP 页面中初始化一个 Java 实例;setProperty 指令用于为 JavaBean 实例的属性设置值;getProperty 指令用于输出 JavaBean 实例的属性。
如果多个 JSP 页面中需要重复使用某段代码,则可以把这段代码定义成 Java 类的方法,然后让多个 JSP 页面调用该方法即可,这样可以达到较好的代码复用。
useBean的语法格式如下:
<jsp:useBean id="name" class="classname" scope="page | request | session | application"/>
其中,id 属性是 JavaBean 的实例名,class 属性确定 JavaBean 的实现类。scope 属性用于指定 JavaBean 实例的作用范围,该范围有以下 4 个值。
➢ page:该 JavaBean 实例仅在该页面有效。
➢ request:该 JavaBean 实例在本次请求有效。
➢ session:该 JavaBean 实例在本次 session 内有效。
➢ application:该 JavaBean 实例在本应用内一直有效。
setProperty 指令的语法格式如下:
<jsp:setProperty name="BeanName" property="propertyName" value="value"/>
其中,name 属性确定需要设定 JavaBean 的实例名;property 属性确定需要设置的属性名;value属性则确定需要设置的属性值。
getProperty的语法格式如下:
<jsp:getProperty name="BeanName" property="propertyName"/>
其中,name 属性确定需要输出的 JavaBean 的实例名;property 属性确定需要输出的属性名。
下面的 JSP 页面示范了如何使用这三个动作指令来操作 JavaBean。
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage=""%>
<!DOCTYPE html>
<html>
<head>
<title> jsp-include 测试 </title>
</head>
<body>
<!-- 创建 lee.Person 的实例,该实例的实例名为p1 -->
<jsp:useBean id="p1" class="lee.Person" scope="page"/>
<!-- 设置p1的 name 属性值 -->
<jsp:setProperty name="pl" property="name" value="crazyit.org"/>
<!-- 设置 p1 的 age 属性值 -->
<jsp:setProperty name="p1" property="age" value="23"/>
<!-- 输出 p1 的 name 属性值-->
<jsp:getProperty name="p1" property="name"/><br/>
<!-- 输出 P1 的 age 属性值 -->
<jsp:getProperty name="p1" property="age"/>
</body>
</html>
以上页面代码示范了使用useBean、setProperty 和 getProperty 来操作 JavaBean 的方法。
对于上面的 JSP 页面中的 setProperty 和 getProperty 标签而言,它们都要求根据属性名来操作 JavaBean 的属性。实际上 setProperty 和 getProperty 要求的属性名,, Java 类中定义的属性有一定的差别,例如 setProperty 和 getProperty 需要使用 name 属性,但 JavaBean 中是否真正定义了 name 属性并不重要,重要的是在 JavaBean 中提供了 setName()和 getName()方法即可。事实上,当页面使用 setProperty 和 getProperty 标签时,系统底层就是调用 setName()和 getName()方法来操作 Person 实例的属性的。
下面是 Person 类的源代码。
package lee;
public class Person
{
private String name;
private int age;
//无参数的构造器
public Person()
{
}
//初始化全部属性的构造器
public Person(String name , int age)
{
this.name = name;
this.age = age;
}
//name 的 setter 和 getter 方法
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
//age 的 setter 和 getter 方法
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return this.age;
}
}
上面的 Person.java 只是源文件,此处将该文件放在 Web 应用的 WEB-INF/src 路径下,实际上 Java 源文件对 Web 应用不起作用,所以此处会使用 Ant 来编译它,并将编译得到的二进制文件放入 WEB-INF/classes 路径下。而且,为 Web 应用提供了新的 class 文件后,必须重启该 Web 应用,让他可以重新加载这些新的 class 文件。
该页面的执行效果如下图所示。.
对于上面三个标签完全可以不使用,将 beanTest.jsp 修改成如下代码,其内部的执行是完全一样的。
<%@page import="lee.Person"%>
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage=""%>
<!DOCTYPE html>
<html>
<head>
<title> jsp-include 测试 </title>
</head>
<body>
<%
// 实例化 JavaBean 实例,实现类为 lee.Person,该实例的实例名为p1
Person p1 = new Person();
//将 p1 放置到 page 范围中
pageContext.setAttribute("p1",p1);
// 设置 pl 的 name 属性值
p1.setName("wawa");
//设置 p1 的 age 属性值
p1.setAge(23);
%>
<!--输出 p1 的 name 属性值 -->
<%=p1.getName()%><br/>
<!--输出 pl 的 age 属性值 -->
<%=p1.getAge()%>
</body>
</html>
使用 useBean 标签时,除在页面脚本中创建了 JavaBean 实例之外,该标签还会将该 JavaBean 实例放入指定 scope 中,所以通常还需要在脚本中将该 JavaBean 放入指定 scope 中,如下面的代码片段所示:
// 将 p1 放入 page 的生存范围中
pageContext.setAttribute("p1",p1);
// 将 p1 放入 request 的生存范围中
request.setAttribute("pl",p1)
// 将 p1 放入 session 的生存范围中
session.setAttribute("p1",p1)
// 将 p1 放入 application 的生存范围中
application.setAttribute("pl",p1);
plugin 指令
plugin 指令主要用于下载服务器端的 JavaBean 或 Applet 到客户端执行。由于程序在客户端执行,因此客户端必须安装虚拟机。
param 指令
param 指令用于设置参数值,这个指令本身不能单独使用,因为单独的 param 指令没有实际意义。param 指令可以与以下三个指令结合使用。
➢ jsp:include
➢ jsp:forward
➢ jsp:plugin
当与 include 指令结合使用时,param 指令用于将参数值传入被导入的页面;当与 forward 指令结合使用时,param 指令用于将参数值传入被转向的页面;当与 plugin 指令结合使用时,则用于将参数传入页面中的 JavaBean 实例或 Applet 实例。
param 指令的语法格式如下:
<jsp:param name="paramName" value="paramValue"/>
关于 param 的具体使用,请参考前面的示例。
评论