JSP内置对象、指令和动作

JSP内置对象、指令和动作

一、内置对象

在 JSP 的 Java 代码块、表达式块等中可以直接使用的引用,称为 JSP 的内置对象。常用的内置对象有九个,分别是:

JSP内置对象、指令和动作_第1张图片
1.jpg

这九个对象在 JSP 的 Java 代码块、表达式块中可以直接使用。之所以可以直接使用,是因为 Java 代码块与表达式块被 JSP 引擎翻译后均出现在了 Servlet 的_jspService()方法中。而这九个对象,就_jspService()方法中的局部变量。在 JSP 的 Java 代码块、表达式块中的代码就是_jspService()方法中的代码,所以在其中可以直接使用。

JSP内置对象、指令和动作_第2张图片
2.jpg

1.1 pageContext

pageContext,页面上下文,其具有一个只在当前页面范围的域属性空间,即其具有setAttribute()方法与 getAttribute()方法。但,由于在当前页面范围,数据不存放到域属性空间也可直接使用,将数据存放到域属性空间反而感觉“多此一举”,所以这些方法并不常用。不过,在同一页面中,为了使用 EL 表达式(后面学习)来访问某变量的值,此时一般使用
pageContext。pageContext 具有一些 get 方法,可以获取到 Request、Response、Session、ServletContext、ServletConfig、page(即当前 Servlet)、exception、out 等另外八个内置对象。

JSP内置对象、指令和动作_第3张图片
3.jpg

但由于这些对象本身就是内置对象,在 JSP 页面中可以直接使用,所以这些方法也并不常用。不过 EL 表达式中,将会经常使用 pageContext 的这些方法。

1.2 application

application,即 ServletContext。所以 ServletContext 所具有的方法,application 都具有。
常用的方法例如,

  • String getInitParameter ():
    获取 web.xml文件的中指定名称的上下文参数值。例 如getInitParameter(“myDBDriver”);会返回字符串“com.mysql.jdbc.Driver”。

  • Enumeration getInitParameterNames():获取 web.xml 文件的中的所有的上下文参数名称。其返回值为枚举类
    型 Enumeration

  • void setAttribute(String name, Object object):
    在 ServletContext 的公共数据空间中,也称为域属性空间,放入数据。这些数据对于 Web应用来说,是全局性的,与整个应用的生命周期相同。当然,放入其中的数据是有名称的,通过名称来访问该数据。

  • Object getAttribute(String name):
    从 ServletContext 的域属性空间中获取指定名称的数据。

  • void removeAttribute(String name):
    从 ServletContext 的域属性空间中删除指定名称的数据。

  • String getRealPath(String path):
    获取当前 Web 应用中指定文件或目录在本地文件系统中的路径,是基于盘符的路径。

  • String getContextPath():
    获取当前应用在 Web 容器中的名称。

1.3 out

out,类型为 javax.servlet.jsp.JspWriter。查看 JavaEE 文档,发现 JspWriter 类继承自 IO流的 Writer 类。即 out 就是一个输出流对象。

JSP内置对象、指令和动作_第4张图片
4.jpg

1.4 page

查看 JSP 翻译为的 Servlet,可以看到 page 对象即 Servlet 对象本身。这个对象在实际应用中并不常用。

JSP内置对象、指令和动作_第5张图片
5.jpg

1.5 exception

在普通的 JSP 页面中是不能使用 exception 内置对象的。因为打开 JSP 翻译为的 Servlet,发现其中并没有 exception 对象。若要在页面中直接使用 exception 对象,则需要配合着 page指令使用。

1.6 其它对象

其它对象,还有 request、response、session,及 config。它们的用法与Servlet的用法相同。只不过是直接使用在了 JSP 页面中了。

二、JSP指令

SP 指令的作用是为当前页面做一些基本的属性设置,为当前的页面的运行提供基本的环境。

根据功能的不同,JSP 中包含三类指令:page 指令,即页面指令;include 指令,即包含指令;及 taglib 指令,即标签库指令。无论哪种指令,其使用的语法格式均为如下形式:

<%@ 指令名称 属性名=属性值 属性名=属性值 ... %>

2.1 page指令

page 指令用于设置当前 JSP 页面的相关信息。一个 JSP 文件中可以包含多个 page 指令。常用的 page 指令的属性意义及用法如下:

(1)pageEncoding属性

pageEncoding 属性用于设置当前 JSP 页面所使用的字符编码格式。即,用户在浏览器中通过右击查看编码所看到的编码格式。

<%@ page pageEncoding="utf-8" %>

其被 JSP 翻译引擎翻译到 Servlet 中的语句,是_jspService()方法中的 setContentType()。

(2)contentType属性

contentType 属性用于设置当前 JSP 页面呈现于用户浏览器中的内容类型,通常为”text/html”类型,即 html 格式的文本。若在 JSP 页面中设置如下:

<%@ page contentType="text/html" %>

注:当内容类型为”text/html”时,使用 pageEncoding 属性与contentType 属性效果是相同的。只有当内容类型不为”text/html”时,才专门使用 contentType 属性指定。在指定字符编码时,这两个属性一般不同时使用。

(3)import属性

import 属性,用于完成在 JSP 页面中导入指定的类。其被 JSP 引擎翻译为 Servlet 中的import 语句。例如,

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

若要导入多个类,则在 import 属性值中可使用逗号将这些类分隔。

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

(4)errorPage属性

errorPage 属性用于指定,当前页面运行过程中发生异常时所要跳转到的页面。

<%@ page errorPage="/error.jsp"%>

<%
    int i = 3/0;
%>

注意,该属性会被翻译到 Servlet 的_jspService()方法中,即这里出现的路径是一个后台路径,而非前台路径。所以这里指定的发生异常后所要跳转的页面,需要使用以斜杠开头的后台路径。

(5)isErrorPage属性

若一个页面中指定了发生异常后所要跳转的页面,将会出现一个问题:异常信息被隐藏了。在控制台看不到异常信息,在所跳转的页面中也看不到异常信息。这对于程序员来说,不是件好事,没有足够的信息提示。

此时,一般是希望当异常发生后,在所要跳转的页面中能够给出相应的异常信息。而异常信息是封装在异常对象 exception 中的。也就是说,我们需要在所要跳转的页面中能够获取到异常对象。此时,就需要将这个所要跳转的页面指定为“错误处理页面”。

当一个页面的 page 指令中设置 isErrorPage 的值为 true 时,表明当前页面为一个“错误处理页面”。默认 isErrorPage 的值为 false。

<%@ page isErrorPage="true" pageEncoding="utf-8"%>

error page

<%
    //在控制台输出异常的堆内存跟踪信息
    exception.printStackTrace();
%>

一旦一个页面 page 指令的 isErrorPage 属性被指定为了 true,查看 JSP 页面所翻译为的Servlet 则会发现,在_jspService()方法中,多出了一个变量 exception。这就是内置对象exception,可以在 JSP 的 Java 代码块、表达式块中直接使用的内置对象。

(6)session属性

session 属性用于指定当前页面中是否可以直接使用内置对象 session。默认为 true,可以使用。查看JSP翻译为的Servlet,可以看到session的创建,使用的是无参方法getSession()。该方法的功能是,若当前具有 session,则使用当前的 session;若当前没有 session,则会新建一个 session。即 session 对象肯定不为 null。

但,有些情况下,我们希望的仅仅是获取到之前已经存在的 session,若之前没有 session,则并不需要创建 session,即让 session 为 null。显示使用默认的 session 属性为 true 已经无法满足需求了。此时,就需要将 session 属性设置为 false,即不使用内置对象session,而是在JSP 页面的代码块中使用 request 的带参getSession()方法。

HttpSession session = request.getSession(false);

若设置 session 属性的值为 false,查看生成的 Servlet 代码,会发现根本就没有出现内置对象 session。

2.2 include指令

include 指令,即包含指令,用于将指定的文件包含到当前的 JSP 文件中。该指令只有一个属性 file,用于指定要包含的文件。

(1)用法:被 include 指定包含的文件,可以是 JSP 动态页面文件,也可以是 HTML 静态页面文件。这里定义一个名为 left.jsp 的动态文件。其中定义了一个变量 sum。

left jsp page
<%
    int sum=100;
%>

再定义一个 index.jsp,不仅将 left.jsp 文件包含了进来,还访问了变量 sum。

index jsp page

<%@ include file="/left.jsp" %>
<%=sum %>

运行结果:

index jsp page
left jsp page
100

(2)静态联编

查看 Tomcat 的 work 目录中相关子目录,发现只生成了一个 index_jsp.java 的 Servlet 源文件,并没有生成 left_jsp.java 文件。那是因为 JSP 翻译引擎在翻译时,会将 include 指令所指定的文件内容直接翻译到当前 JSP 对应的 Servlet 中,形成一个.java 文件。这就说明一个问题:这个包含操作是在编译之前完成的,是在编译之前由 JSP 翻译引擎完成的,不是在程序运行期完成的。这种包含是一种静态包含,称为静态联编。

由于在编译期就将这些文件合并为了一个 Servlet 文件,所以,整个过程就一个_jspService()方法。也就是说,这些文件之间是可以相互访问局部变量的。只要满足变量声明与使用的先后顺序即可。

JSP内置对象、指令和动作_第6张图片
6.jpg

(3)为什么使用include指令

对于一个包含很多页面的系统或站点,很多页面的头部、底部,或者左侧部分都是相同的。为了减少页面定义的重复性工作,为了便于对这些相同部分的修改,我们将这些相同的部分,分别定义为了多个页面。然后,让其它需要使用这些部分的页面,使用 include 指令将这些部分包含进来。这样的话,不仅大大减少了工作量,还做到了对于页面修改的“一改全改”效果。

三、JSP动作(Action)

在 JSP 页面中大量使用 Java 代码块、表达式块等内容,会使 JSP 页面看起来“杂乱无章”。为了使 JSP 页面看得简洁明了,为了简化 Java 代码,一般情况下,我们会尽量少的使用 Java代码块与表达式块。取而代之的则是使用 EL 表达式、JSTL 标签,及 JSP 动作。

JSP 动作是指,使用系统定义好的标签来完成本应由 Java 代码来完成的功能。

JSP 动作的语法格式为:



JSP 动作很多,但在实际开发时常用的就两个:转发动作与包含动作。
这两份个动作的完成,底层使用的是 RequestDispatcher 的 forward()与 include()方法实现的。而这两份种请求转发方式的本质区别是,标准输出流的开启时间不同。forward()方式的标准输出流是在目标资源中开启的标准输出流,而 include()方式的标准输出流则是在当前发出包含运作的页面中开启的。所以,forward()动作的发起页面中是无法向标准输出流中写入数据的;而 include()动作的发起页面及目标页面中均可向标准输出流中写入数据。这两份个动作都具有一个 page 属性,用于指定要转向的页面。

3.1 forward动作

页面中一旦具有了forward动作,那么当前页面中的所有显示的内容都将无法显示。因为页面直接转发到了下一个页面。

JSP内置对象、指令和动作_第7张图片
7.jpg

(1)定义index.jsp页面

<%@ page contentType="text/html; charset=utf-8" %>

页面中只要具有了forward动作,当前页面中的所有要显示的内容都将无法显示。因为页面直接转发到了下一个页面。

<%
    request.setAttribute("user","beijing");
%>

(2)定义next.jsp页面

next page

<%=request.getAttribute("user") %>

打开 JSP 页面翻译为的 Servlet,可以看到要跳转的路径出现在了 Servlet 代码中,即可以使用后台路径。

JSP内置对象、指令和动作_第8张图片
8.jpg

注意,在 JSP 动作中,没有用于完成重定向的动作。

3.2 include动作

include 动作用于完成将指定页面包含到当前页面中的功能。

JSP内置对象、指令和动作_第9张图片
9.jpg

(1)用法

定义index.jsp页面

index page
<%
    int sum=50;
%>


index page sum = <%=sum %>

定义left.jsp页面

left page
<%
    int sum = 100;
%>

left page sum = <%=sum %>

运行结果:

index page
left jsp page
left page sum = 100
index page sum = 50

(2)动态联编

打开 Tomcat 的 work 目录的相关子目录,可以看到有两个.java 文件:index_jsp.java 与left_jsp.java。也就是说,包含动作的包含,是在运行期完成的,而非在编译期。这个包含动作,是在程序运行过程中,由 index_jsp 文件中的_jspService()方法通过 JspRuntimeLibrary 类
的 include()方法调用了 left_jsp 文件中的_jspService()方法。在运行期所执行的这种包含,称为动态联编。

(3)静态联编与动态联编的应用场景

在静态联编与动态联编均可使用时,一般使用静态联编。因为在程序运行时只存在一个Servlet,对资源的消耗较少,且不存在调用问题,执行效率较高。若在两个文件间需要共享同一变量,此时只能使用静态联编。若在两个文件间存在同名变量,且不能混淆,此时只能使用动态联编。

你可能感兴趣的:(JSP内置对象、指令和动作)