JSP——JavaServer Page中的隐式对象(implicit object)、指令(directive)、脚本元素(scripting element)、动作(action)、EL表达式

时间:2022-09-19 14:27:32

目录

1.JSP概述

2.注释(comment)

  2.1.JSP注释

  2.2.HTML注释

3.隐式对象(implicit object)

  3.1.隐式对象清单

  3.2.request对象

  3.3.out对象

  3.4.pageContext对象

4.指令(driective)

  4.1.page指令

    4.1.1.page指令的属性

    4.1.2.用法

5.脚本元素(scripting element)

  5.1.Scriptlet

  5.2.表达式

  5.3.声明

  5.4.关闭脚本元素

6.动作(action)

  6.1.include

  6.2.forward

7.EL表达式

  7.1.EL语法

  7.2.EL隐式对象清单

8.JSTL

  8.1.下载JSTL

  8.2.标签类库

  8.3.常用标签

    8.3.1.The url Tag

    8.3.2.The if Tag

    8.3.3.The choose/when/otherwise Tag

    8.3.4.The forEach Tag

    8.3.5.The formatDate Tag

1.JSP概述

JSP页面其实就是一个Servlet。但使用起来比编写Servlet要容易得多。

JSP页面是在JSP容器中运行的。Servlet容器一般也是JSP容器。例如Tomcat就是一个Servlet/JSP容器。

2.注释(comment)

JSP页面中可以使用两种注释:JSP注释、HTML注释。

2.1.JSP注释

以开头,以结尾。例如:

<%-- 这是一个JSP注释 --%>

JSP注释不会被发送到浏览器,也不能够嵌套。

2.2.HTML注释

<!-- 这是一个HTML注释 -->

HTML注释会被发送到浏览器。

3.隐式对象(implicit object)

Servlet容器将几个对象传递给它所运行的Servlet。例如,在Servlet的service方法中获得HttpServletRequest和HttpServletResponse,并在init方法中获得ServletConfig。此外,还可以通过HttpServletRequest对象调用getSession方法获得一个HttpSession。

在JSP中,可以通过使用隐式对象的方式来获取这些对象。

3.1.隐式对象清单

对象

类型

request

javax.servlet.http.HttpServletRequest

response

javax.servlet.http.HttpServletResponse

out

javax.servlet.jsp.JspWriter

session

javax.servlet.httpHttpSession

application

javax.servlet.ServletContext

config

javax.servlet.ServletConfig

pageContext

javax.servlet.jsp.PageContext

page

javax.servlet.jsp.HttpJspPage

exception

java.lang.Throwable

3.2.request对象

request对象表示由Servlet/JSP容器传给Servlet的service方法的HttpServletRequest对象。可以像使用HttpServletRequest对象的引用一样使用request。

如,以下代码是从HttpServletRequest对象中获取userName参数:

<%
String userName = request.getParameter("userName");
%>

3.3.out对象

out对象引用javax.servlet.jsp.JspWriter,它类似于在HttpServletResonse中调用getWriter()之后得到的java.io.PrintWriter。可以调用它的print方法重载PrintWriter,将消息发送到浏览器。

3.4.pageContext对象

pageContext是指为页面创建的javax.servlet.jsp.PageContext。它提供了一些方法可以访问request、response等对象,不过这些方法用处不大,因为我们可以通过隐式对象来访问这些对象。

真正有用的是PageContext允许利用Expression Language访问这些对象。

PageContext提供的另一些重要的方法是那些存取属性,如getAttribute和setAttribute方法。属性可以保存在以下四种范围中:page、request、session以及application。

page范围最窄,保存在这里的属性只能在同一个JSP页面中使用。

request范围是指当前的ServletRequest。

session范围是指当前的HttpSession。

application范围是指ServletContext。

4.指令(directive)

指令是一种JSP句法元素,它告诉JSP转换器应该如何将某个JSP页面转换成Servlet。

JSP 2.2中定义了几个指令:page、include、taglib、tag、attribute以及variable。

其中最重要的是:page和include。

4.1.page指令

语法

<%@ page attribute1="value1" attribute2="value2" ... %>

@和page之间的空格是可选的,attribute1、attribute2等都是page指令的属性。

4.1.1.page指令的属性

import

指定要导入的一种或多种Java类型,供本页的Java代码所用。

导入List接口:

<%@ page import="java.util.List" %>

利用通配符*可以导入整个包:

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

导入多重类型时,两种类型之间要用逗号隔开:

<%@ page import="java.util.ArrayList, java.util.Calendar, java.io.PrintWriter" %>

下面这些包的是隐式导入的:

javax.servlet.*;
javax.servlet.http.*;
javax.servlet.jsp.*;

怎么知道它们是隐式导入的呢?只要查看一个由JSP生成的Servlet类,即可得知。

session

值为true时,表示这个页面参与Session管理;

值为false时,表示不参与Session管理。

默认值为true,意味着如果之前还没有javax.servlet.http.HttpSession实例,那么调用这个JSP页面时会创建一个。

buffer

指定隐式对象out的缓冲区大小,以千字节为单位。强制以kb为后缀。

缓冲区的默认容量大于或等于8kb,具体取决于JSP容器。

这个属性还可以设置为none,表示不适用缓存,但这样会导致输出的内容直接被写入相应的PrintWriter。

autoFlush

默认值为true,表示当缓冲区满时,被缓存的输出应当自动刷新。

值为false时,表示只有在调用隐式对象response的flush方法时,才进行刷新缓冲区。因此,当缓冲区益处时,就会抛出一个异常。

isThreadSafe

表示页面中实现的线程安全级别。建议JSP的作者不要使用这个属性,因为它会产生一个包含不建议使用的代码的Servlet。

info

指定所生成的Servlet的getServletInfo方法的返回值。

errorPage

表示负责处理该页面可能会出现的错误的页面。

isErrorPage

表名这个页面是否负责处理错误。

contentType

指定该页面隐式对象response的内容类型,其默认值为text/html。

pageEncoding

指定该页面的字符编码,其默认值为ISO-8859-1。

isElIgnored

表名是否忽略EL表达式。

language

指定这个JSP页面使用的脚本语言,其默认值为java,这个值是JSP 2.2中唯一有效的值。

extends

指定这个JSP页面的实现类必须扩展的超类。该属性很少使用。

deferredSyntaxAllowedAsLiteral

指明是否允许使用字符序列“#{”作为该页面和编译单元的String字面值。

默认值为false。

与EL表达式有关。

trimDirectiveWhitespaces

表名是否从输出内容中删除只包含空格的模板文本。

默认值为false。

4.1.2.用法

page指令可以出现在页面中的任何位置。只是当它包含contentType或者pageEncoding属性时,它必须放置在所有的模板数据之前,并且是在利用Java代码发送任何内容之前。因为必须在发送任何内容之前设置内容类型和字符编码。

page指令可以多次出现。但是在多个page指令中多次出现的同一个属性,它的值必须一致,只有import属性除外。

4.2.include指令

利用include指令可以将另一个文件的内容放到当前的JSP页面中。在一个JSP页面中可以使用多个include指令。

如果某部分特殊的内容需要被其他页面所用,或者被处于不同位置的某个页面所用,那么将这部分内容做成一个include文件是很有帮助的。

语法

<%@ include file="url" %>

此处@和include之间的空格是可选的,并且url是表示一个include文件的相对路径。

如果url以一个正斜线(/)开头,那么其在服务器中就会被解读成是一条绝对路径。

如果不是以正斜线开头,则会被解读为相对于当前JSP页面的路径。

5.脚本元素(scripting element)

脚本元素是JSP的一种句法,它将Java代码合并成一个JSP页面。

脚本元素有三种类型:Scriptlet、声明和表达式。

5.1.Scriptlet

Scriptlet是一段Java代码块,它以<%开头,以%>结束。

CODE

<%@ page import="java.util.Enumeration"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Scriptlet example</title>
</head>
<body>
<b>Http headers:</b><br/>
<%-- first scriptlet --%>
<%
for (Enumeration<String> e = request.getHeaderNames();
e.hasMoreElements(); ) {
String header = e.nextElement();
out.println(header + ": " + request.getHeader(header)
+ "<br />");
} String message = "Thank you.";
%> <hr /> <%-- second scriptlet --%>
<%
out.println(message);
%> </body>
</html>

解析

上述JSP页面中有两个Scriptlet。注意,在一个Scriptlet中定义的变量,对于它后面的其他Scriptlet是可见的。

5.2.表达式

表达式的运算结果会被填入隐式对象out的print方法中。

表达式以<%开头,并以%>结束。

例子:

Today is <%=java.util.Calendar.getInstance().getTime()%>

注意,表达式后面不需要分号。

对于这个表达式,JSP容器会先运算java.util.Calendar.getInstance().getTime(),然后将结果传给out.print()。因此,它与下面这个Scriptlet的结果是一样的:

Today is
<%=
out.print(java.util.Calendar.getInstance().getTime());
%>

5.3.声明

声明能够在JSP页面中使用的变量和方法。声明凡在<%!  %>标签中间。

CODE

<%!
public String getTodayDate() {
return new java.util.Date();
}
%>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Declarations</title>
</head>
<body>
Today is <%=getTodayDate() %>
</body>
</html>

5.4.关闭脚本元素

随着JSP 2.0中的Expression Language的发展,建议做法是使用EL表达式来访问服务器端的对象,而不是在JSP页面中编写Java代码。

因此,原本开启的JSP 2.0脚本元素,可以通过在部署描述符的<jsp-property-group>中定义一个scripting-invalid元素,将其关闭。

例子:

<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>

6.动作(action)

动作也是JSP中的句法,它们被编译成执行某个操作的Java代码,例如访问某个Java对象,或者调用某个方法。

6.1.include

include动作用于动态的包含另一个资源,它可以包含另一个JSP页面、一个Servlet或者一个静态的HTML页面。

例子

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Include action</title>
</head>
<body>
<jsp:include page="jspf/menu.jsp">
<jsp:param name="text" value="How are you?" />
</jsp:include>
</body>
</html>

include指令和include动作的区别

使用include指令时,这种包含是发生在页面转换的时候,例如JSP容器将页面转换成一个Servlet的时候。

使用include动作时,这种包含则是发生在请求的时候。因此,可以利用include动作传递参数。

使用include指令时,被包含资源的文件扩展名并不重要。

使用include动作时,文件扩展名必须为jsp,以便它能够将其作为一个JSP页面进行处理。

6.2.forward

forward动作是将当前页面跳转到另一个不同的资源。

例如,下面的forward动作就是将当前页面跳转到login.jsp页面:

<jsp:forward page="jspf/login.jsp">
<jsp:param name="text" value="Please login" />
</jsp:forward>

7.EL表达式

7.1.EL语法

EL表达式是以${开头,以}结束。一个EL表达式的构造如下:

${ expression }

访问对象属性:

${ object["propertyName"] }
${ object.propertyName }

7.2.EL隐式对象

在一个JSP页面中南,可以通过JSP脚本访问JSP隐式对象。但是如果要编写无脚本的JSP页面,那么就不能访问这些隐式对象了。

EL通过提供一组它自己的隐式对象,可以用来访问各种对象。

EL隐式对象清单

对象

描述

pageContext

当前JSP页面的javax.servlet.jsp.PageContext

initParam

包含所有context初始化参数并以参数名称作为键的Map

param

包含所有请求参数并以参数名称作为键的Map。每个键的值就是指定名称的第一个参数值。因此,如果有两个同名的请求参数,将只有第一个参数可以利用param对象获取到。要想或有所有同名参数的值,则要使用params对象。

paramValues

包含所有请求参数并以参数名称作为键的Map。每个键的值就是包含所有指定名称的一个字符串数组。如果该参数只有一个值,它仍然会返回一个只有一个元素的数组。

header

包含所有请求标头并以标头名称作为键的Map。每个键的值就是指定标头名称的第一个标头。换句话说,如果某个标头有多个值,那将只返回第一个值。想要获得多值标头,则要使用headerValues对象。

headerValues

包含所有请求标头并以标头名称作为键的Map。每个键的值就是包含指定标头名称所有值的一个字符串数组。如果一个标头只有一个值,也将返回一个只有一个元素的数组。

cookie

包含当前请求对象中所有Cookie对象的Map。Cookie的名称就是Map的键,每一个键都映射到一个Cookie对象。

applicationScope

包含ServletContext对象中所有属性并以属性名称作为键的Map

sessionScope

包含HttpSession对象中所有属性并以属性名称作为键的Map

pageContext

pageContext对象表示当前JSP页面的javax.servlet.jsp.PageContext。它包含所有的JSP隐含对象。

8.JSTL

JavaServer Pages Standard Tag Library(JSTL)是一个定制标签类库的集合,用于解决一些常见的问题,例如迭代一个映射或者集合、条件测试、XML处理,甚至数据库访问和数据操作等。

8.1.下载JSTL

需要下载两个包:JSTL API和JSTL实现。JSTL API中包含javax.servlet.jsp.jstl包,由JSTL规范中定义的类型组成。JSTL实现则包含了相关的实现类。必须将两个jar包都加入项目才能使用。

如果使用的是Servlet容器(如Tomcat、Jetty),那么其中不会包含这两个包,必须是Java EE应用服务器才行,例如WildFly、TomEE,和GlassFish。

下载Java EE应用程序服务器,然后从其中的lib目录下找到这两个包。

例如:

Apache TomEE 7.0.1

apache-tomee-webprofile-7.0.\lib\openejb-jstl-1.2.jar

GlassFish 4.1.1

glassfish4\glassfish\modules\javax.servlet.jsp.jstl.jar
glassfish4\glassfish\modules\javax.servlet.jsp.jstl-api.jar

WildFly 9.0.2

wildfly-9.0..Final\modules\system\layers\base\javax\servlet\jstl\api\main\jboss-jstl-api_1.2_spec-1.1..Final.jar

从这几个服务器中找到列出的相应的包即可,任选任何一个服务器下的包即可,因为他们是遵循同一个标准编写的。

有的服务器下面只有一个包是因为其将JSTL API和JSTL实现编译到一个jar文件中了。

8.2.标签类库

Core
变量支持、流向控制、URL管理、其他

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

I18n
语言环境、消息格式化、数字和日期格式化

<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>

Functions
集合、字符串操作

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

8.3.常用标签

8.3.1.The url Tag

为URL拼接当前上下文路径

<img alt="" src="<c:url value="/images/logo.png" />">

8.3.2.The if Tag

对某个条件进行测试,如果条件成立则处理标签内的主体内容,否则不处理。
可以使用 var 属性设置域变量名,使用 scope 属性指定其作用范围

<c:if test="${detail.todo.status == 0}">
  <option value="0">待办</option>
</c:if>

8.3.3.The choose/when/otherwise Tag

分支语句结构,类似于 switch 语句结构

<c:choose>
<c:when test="${param.status=='full'}">
You are a full member
</c:when>
<c:when test="${param.status=='student'}">
You are a student member
</c:when>
<c:otherwise><!-- 可选 -->
Please register
</c:otherwise>
</c:choose>

8.3.4.The forEach Tag

用于迭代一个集合对象
可以迭代的对象
java.util.Collection 的实现
java.util.Map 的实现
对象或者基本类型的数组
java.util.Iterator
java.util.Enumeration
有两种用法,一种是将标签中的内容重复一定的次数,另一种是迭代一个集合对象

重复内容

<c:forEach [var="varName"] begin="begin" end="end" step="step">
body content
</c:forEach>

迭代集合

<c:forEach items="collection" [var="varName"] [varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]>
body content
</c:forEach>

属性
var
String
引用当前迭代项目的域变量名称

items
支持的任何类型
要迭代的对象集合

varStatus
String
保存迭代状态的域变量名称,它的值类型为 javax.serlet.jsp.jstl.core.LoopTagStatus

begin
int
如果指定了items,那么迭代将从处于指定索引的项开始,该集合中的第一个项索引为0
如果没有指定items,迭代将从该值设定的索引开始,并且begin的值必须大于等于0

end
int
如果指定了items,那么迭代结束处于指定索引的项(包括该项)
如果没有指定items,那么当索引到达指定值时,迭代结束

step
int
步长,迭代会从集合的第一个step开始,根据step步长逐个进行
如果设置step属性,必须大于等于1

8.3.5.The formatDate Tag

用于格式化日期

<f:formatDate value="${detail.todo.createDate}" pattern="yyyy-MM-dd HH:mm:ss" />