JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记

JavaWeb学习笔记

哔哩哔哩蛙课网【动力节点】JavaWeb-Eclipse版学习视频网址

解析 归属 备注
Java Server Pages java 服务器页面 JSP基础
out. write () JSP 写出 代码 JSP基础 属于 IO流
<% %> Java 代码块 JSP基础 翻译到_jspService()
<%! %> 声明语句块 JSP基础 可以声明变量、方法
<%= %> 表达式块 JSP基础 out.print()
pageContext 页面上下文 pageContext
set、getAttribute() 设置、获得属性 pageContext 可获得八个内置对象
application 应用 pageContext 即ServletContext
page 页面指令 pageContext 即Servlet对象本身
exception 例外 pageContext 要配合着 page指令使用
import 导入指定的类 pageContext
errorPage 错误页面 pageContext 发生异常时的跳转
session 一会 JSP page 指令 2无参方法,没有就创建一个
include 包含指令 JSP指令、动作
forward 转发动作 JSP 动作
pageContextpageConext 页相关域页相关域 域属性空间域
requestrequest 请求域请求域 域属性空间域
sessionsession 会话域会话域 域属性空间域
applicationapplication 应用域应用域 域属性空间域
Expression Language EL表达式 EL表达式
${key.属性} EL 的获得属性方式 EL表达式
${key[索引]} EL 获得索引 EL表达式
${attributeName.mapKey} EL 获得Map EL表达式
${pageContext.request} 获取 request EL表达式
${param.参数名} 获得请求中指定值 EL表达式
${paramValues.参数名[索引]} 获得某数组值 EL表达式
${initParam.初始化参数名} 获得指定初始化的值 EL表达式
${.tld文件名:内方法名(参数)} 自定义 EL 函数 EL表达式
Standard Tag Library 标准标签库 JSTL
SimpleTag 标签处理器 自定义标签 自定义标签的功能接口
SimpleTagSupport 标签处理器实现类 自定义标签
标签体 注册标签处理器
empty 空,没有标签
scriptless 无脚本 无java脚本,但能EL计算
tagdependent 标记相关 会将 EL 传递成普通字符串
invoke(Writer) 调用,写 JspFragment 写入到输出流中
false 意思只能为常量 注册标签处理器 Runtime Expression Value
forEachList 遍历 list 集合 自定义标签
forEach 遍历其他 自定义标签 除去Int等基本数据类型
Arrays.asList() 数组转 list 集合 forEach
Collection 收集 forEach doTag()方法中的遍历对象
getClass().isArray() 判断是否为数组 forEach
JSP Standard Tag Library JSTL 标准标签库 JSTL
c:set 进行变量定义 JSTL
c:remove 删除域属性空间内变量 JSTL
c:out 页面输出 JSTL default 预设,当没有值时输出
c:catch 捕获异常 JSTL
c:choose 多分支判断 JSTL
c:otherwise 其他 c:choose
varStatus = 引用型变量 c:forEach 添加序号
fmt:formatDate 不同模式的格式化日期 格式化标签库
fmt:parseDate 字符串转日期类型 格式化标签库
fmt:formatNumber 对数字进行格式化 格式化标签库
fmt:parseNumber 字符串转换为数组类型 格式化标签库
View 层 接收用户请求层 三层框架
Service 层 业务逻辑层 三层框架
Dao 层 操作数据库层 三层框架
trim() 去掉前后文
executeQuery() 执行结果查询 SQL

1、JSP 基础

1.1、什么是 JSP

JSP,即 Java Server Pages,Java 服务器页面,即运行在服务器端的页面。它是由 Sun 公司倡导,许多国际性大公司参与,一起建立的一种动态网页技术。JSP 技术是在传统的静态网页 HTML文件中插入 Java 代码片断和 JSP 标签后形成的一种文件,其后缀名为 .jsp。使用 JSP 开发的 Web应用是跨平台的,既能在 Linux 上运行,也能在其他操作系统上运行。

在 Eclipse 下的 Web 工程的 WebContent 目录中新建一个 JSP 文件,例如新建一个 index.jsp文件。
JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第1张图片

在 jsp 文件中写入如下内容:


Hello JSP Woeld!

然后运行这个 Web 项目,在浏览器中即可看到 “ Hello JSP World! ” 字样。

打开 Eclipse 的工作空间 workspace 的如下子目录,可看到两个文件:
workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第2张图片
源码文件 index_jsp.java 就是由刚才的 Web 项目中的 Index.jsp 文件转变成的 Java 文件。而 index_jsp.class 文件为 index_jsp.java 文件编译后的字节码文件。

我们的.jsp 文件

打开这个 index_jsp.java 文件,发现其继承自 HttpJspBase 类。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pmZSz5WE-1628937484672)(JavaWeb-jsp.assets/image-20210808114855231.png)]
使用Open Type 查询 HttpJspBase,连接 Tomcat 的源码
JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第3张图片

打开 Tomcat 的源码目录中的 java 子目录,在其中查看 HttpJspBase 的源码,发现其继承自 HttpServlet。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第4张图片

也就是说,JSP 文件的本质是 Servlet

  • 只不过,JSP 与 Servlet 不同的是,JSP 是专门用于进行数据展示的 Servlet,其有特殊的写法

  • 而普通的 Servlet 是用于完成业务逻辑处理的

由于 Servlet 是运行在单例多线程环境下的,所以 JSP 同样也是运行在单例多线程环境下的。

1.2、JSP 规范

将 JSP 页面翻译为 Servlet 的过程,是由 Tomcat 完成。

在 Tomcat 中内置了一个 JSP 翻译引擎,当第一次访问该 JSP 页面时,翻译引擎会将 JSP 页面翻译为 Servlet 的.java 文件,再将其编译为.class 文件进行运行。

SUN 公司制定的 JavaEE 规范中包含两个很重要的子规范:Servlet 规范,及 JSP 规范。

其中 JSP 规范中就包含了如何将 JSP 页面翻译为 Servlet。例如, 页面中的 HTML、 JavaScript,JSPCSS、及普通文本部分,均会被翻译到 out. write ()中。

Tomcat 中的 JSP 翻译引擎,就遵循了这个 JSP 规范。

1.3、JSP 注释

在 JSP 页面中使用注释,可以将要注释的内容使用<%-- --%>括起来。

当然,在 JSP 页面中也可以使用 HTML 的注释。 但它们的使用效果是不同的。

  • HTML 注释会被 JSP 翻译引擎翻译到 Servlet 的 out.write()中;而 JSP 注释则会被 JSP 翻译引擎忽略,在 Servlet 中是看不到的。

  • 在客户端浏览器查看源码时,HTML 注释是可以查看到的;但 JSP 注释在客户端是查看不到的。

  • 例如,在 JSP 页面中写入如下注释:


	This is my JSP page.
<%-- 这是JSP注释 --%>

查看 Tomcat 服务器的 work 目录中由 JSP 引擎翻译过的 Servlet,可以看到:
JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第5张图片

查看客户端浏览器的源码文件,可以看到:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第6张图片

1.4、JSP 的 Java 代码块

JSP 的 Java 代码块也称为 JSP 小脚本,是以<% %>括起来的部分,其中可以编写 Java代码。

编写在 Java 代码块中的代码,会被 JSP 翻译引擎将其置入到 Servlet 的_jspService()方法中作为方法中的 Java 语句出现。所以,其中存放的必须是以分号结尾的 Java 语句。

需要注意的是,JSP 代码块可以放置在 JSP 页面的任意位置,可以放置任意数量。但它们都会被按照顺序放置到 Servlet 的_jspService()方法中。也就是说,其执行顺序是与其在 JSP页面中的出现顺序是一致的。例如,
JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第7张图片

被翻译到 Servlet 的_jspService()方法中为:
JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第8张图片

由于 JSP 小脚本是被翻译到了 Servlet 的_jspService()方法中,所以 JSP 小脚本中是不能出现如下内容的:

  • 声明的变量是不能添加权限访问控制符的
  • 不能定义方法
  • 不能定义静态语句块

但是能出现 Java 注释语句 // /* */

1.5、JSP 的声明语句块

在 JSP 页面中使用<%! %>括起来的部分,称为声明语句块。声明语句块中的内容,将被 JSP 引擎翻译到 Servlet 的类体中,没有包含到哪个方法体中。

这样的话,在 JSP 的声明语句块中就可声明实例变量、实例方法、静态方法、静态代码块等内容。并且,这些内容均可被 JSP 的 Java 代码块中代码访问。因为它们原本就是一个Servlet 类中的代码。

不过,还是不建议在 JSP 的声明语句块中声明实例变量。因为 JSP 是运行在单例多线程环境下的,实例变量将会引起线程安全问题。

需要注意的是,在 JSP 的声明语句块中,是不能编写普通的 Java 语句的。否则的话,这些语句将会直接出现在 Servlet 的类体中。

声明语句块也可以定义在 JSP 页面的任意位置,且可以定义任意多个。
JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第9张图片

在 JSP 的 Java 代码块与声明语句块中,均可使用 Java 的单行注释与多行注释。该注释将会出现在 Servlet 中的相应位置。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第10张图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nTFUwepM-1628937484709)(JavaWeb-jsp.assets/image-20210808164346670.png)]

1.6、JSP 的表达式块

在 JSP 页面中使用<%= %>括起来的部分,称为表达式块。其可在 JSP 页面中输出变量、常量,及它们组成的各种表达式的值。

注意,是表达式,而不是语句,是没有分号的。该表达式将被 JSP 引擎翻译到_jspService()方法的 out.print()方法中输出。例如:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第11张图片

被 JSP 引擎翻译为 Servlet 后为:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第12张图片

2、JSP 核心

2.1、内置对象

在 JSP 的 Java 代码块、表达式块等中可以直接使用的引用,称为 JSP 的内置对象。

常用的内置对象有九个,分别是:
JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第13张图片

这九个对象在 JSP 的 Java 代码块、表达式块中可以直接使用。只所以可以直接使用,是因为 Java 代码块与表达式块被 JSP 引擎翻译后均出现在了 Servlet 的_jspS ervice()方法中。

而这九个对象,就是_jspService()方法中的局部变量。

在 JSP 的 Java 代码块、表达式块中的代码就是_jspService()方法中的代码,所以在其中可以直接使用。

2.1.1、pageContext

pageContext,页面上下文,其具有一个只在当前页面范围的域属性空间,即其具有setAttribute()方法与 getAttribute()方法。

但,由于在当前页面范围,数据不存放到域属性空间也可直接使用,将数据存放到域属性空间反而感觉“多此一举” 所以这些方法并不常用。

不过,在同一页面中,为了使用 EL 表达式(后面学习)来访问某变量的值,此时一般使用

pageContext

pageContext 具有一些 get 方法,可以获取到 Request、Response、Session、ServletContext、ServletConfig、page(即当前 Servlet)、exception、out 等另外八个内置对象。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第14张图片

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

2.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 容器中的名称。

2.1.3、out

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第15张图片

2.1.4、page

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第16张图片

2.1.5、exception

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

2.1.6、其它对象

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

2.2、JSP 指令(directive)

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

根据功能的不同,JSP 中包含三类指令:

  • page 指令,即页面指令;

  • include 指令,即包含指令;

  • 及 taglib 指令,即标签库指令。

无论哪种指令,其使用的语法格式均为如下形式:

在这里插入图片描述

taglib 指令在后面学习 JSTL 时再进行讲解。

2.2.1、page 指令

page 指令用于设置当前 JSP 页面的相关信息。一个 JSP 文件中可以包含多个 page 指令。

常用的 page 指令的属性意义及用法如下:

pageEncoding 属性

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

在这里插入图片描述

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

在这里插入图片描述

contentType 属性

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

在这里插入图片描述

对应 JSP 翻译引擎翻译过的 Servlet 中的语句,则为_jspService()方法中的如下语句:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第17张图片

但,若直接通过 contentType 属性指定内容类型与字符编码:

在这里插入图片描述

则生成的 Servlet 语句仍为:

在这里插入图片描述

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

import 属性

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

例如:

在这里插入图片描述

在 Servlet 中被翻译为了:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第18张图片

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

在这里插入图片描述

在 Servlet 中将被翻译为多个 import 语句:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第19张图片

修改年月日格式

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page import="java.util.*,java.text.*"%>



Insert title here


	<%
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		Date now = new Date();
		out.print("now = " + sdf.format(now));
	%>



errorPage 属性

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第20张图片

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

isErrorPage 属性

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

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

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第21张图片

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

session 属性

session 属性用于指定当前页面中是否可以直接使用内置对象 session。默认为 true,可以使用。查看 JSP 翻译为的 Servlet,可以看到 session 的创建,使用的是无参方法 getSession()。

该方法的功能是,若当前具有 session,则使用当前的 session;若当前没有 session,则会新建一个 session。即 session 对象肯定不为 null。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第22张图片

但,有些情况下,我们希望的仅仅是获取到之前已经存在的 session,若之前没有 session,则并不需要创建 session,即让 session 为 null。

显示使用默认的 session 属性为 true 已经无法满足需求了。此时,就需要将 session 属性设置为 false,即不使用内置对象 session,而是在JSP 页面的代码块中使用 request 的带参 getSession()方法。

HttpSession session = request.getSession(false);

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第23张图片

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page session="false"%>



Insert title here


	<%
		// 使用request的getSession()的原则:
		// 若向Session域中存放数据,则使用getSession(true),即getSession()
		// 若从Session域中读取数据,则使用getSession(false)
		HttpSession session = request.getSession(false);
		if(session != null) {
			String user = (String) session.getAttribute("user");
			out.print("user = " + user);
		}
		out.print("session = " + session);
	%>



2.2.2、include 指令

include 指令,即包含指令,用于将指定的文件包含到当前的 JSP 文件中。

该指令只有一个属性 file,用于指定要包含的文件。

用法

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第24张图片

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第25张图片

运行结果为:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第26张图片

静态联编

查看 Tomcat 的 work 目录中相关子目录,发现只生成了一个index_jsp.java的 Servlet 源文件,并没有生成 left_jsp.java文件。

那是因为 JSP 翻译引擎在翻译时,会将 include 指令所指定的文件内容直接翻译到当前 JSP 对应的 Servlet 中,形成一个 .java 文件。

这就说明一个问题:这个包含操作是在编译之前完成的,是在编译之前由 JSP 翻译引擎完成的,不是在程序运行期完成的。这种包含是一种静态包含,称为静态联编。

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第27张图片

为什么使用 include 指令

对于一个包含很多页面的系统或站点,很多页面的头部、底部,或者左侧部分都是相同的。

为了减少页面定义的重复性工作,为了便于对这些相同部分的修改,我们将这些相同的部分,分别定义为了多个页面。然后,让其它需要使用这些部分的页面,使用 include 指令将这些部分包含进来。

这样的话,不仅大大减少了工作量,还做到了对于页面修改的“一改全改”效果。

2.3、JSP 动作(Action)

在 JSP 页面中大量使用 Java 代码块、表达式块等内容,会使 JSP 页面看起来“杂乱无章”。

为了使 JSP 页面看得简洁明了,为了简化 Java 代码,一般情况下,我们会尽量少的使用 Java代码块与表达式块。

取而代之的则是使用 EL 表达式、JSTL 标签(后面学习),及 JSP 动作。

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

JSP 动作的语法格式为:

在这里插入图片描述

在这里插入图片描述

JSP 动作很多,但在实际开发时常用的就两个:转发动作与包含动作。

这两份个动作的完成,底层使用的是 RequestDispatcher 的 **forward()**与 **include()**方法实现的。

而这两份种请求转发方式的本质区别是,标准输出流的开启时间不同。

forward()方式的标准输出流是在目标资源中开启的标准输出流, include()方式的标准输出流则是在当前发而出包含运作的页面中开启的。

所以,forward()动作的发起页面中是无法向标准输出流中写入数据的;而 include()动作的发起页面及目标页面中均可向标准输出流中写入数据。

这两份个动作都具有一个 page 属性,用于指定要转向的页面。

2.3.1、forward 动作

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第28张图片

定义 index.jsp 页面

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第29张图片

定义 next.jsp 页面

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第30张图片

运行结果:只显示 next.jsp 内容,index.jsp 未显示

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第31张图片

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

2.3.2、include 动作

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

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第32张图片

用法

定义 index.jsp 页面

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第33张图片

定义 left.jsp 页面

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第34张图片

运行结果:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第35张图片

动态联编

打开 Tomcat 的 work 目录的相关子目录,可以看到有两个.java 文件:index_jsp.java 与left_jsp.java。

也就是说,包含动作的包含,是在运行期完成的,而非在编译期。

这个包含动作,是在程序运行过程中,由 index_jsp 文件中的_jspService()方法通过 JspRuntimeLibrary 类的 include()方法调用了 left_jsp 文件中的_jspService()方法。

在运行期所执行的这种包含,称为动态联编。

静态联编与动态联编的应用场景

​ 在静态联编与动态联编均可使用时,一般使用静态联编。因为在程序运行时只存在一个Servlet,对资源的消耗较少,且不存在调用问题,执行效率较高。

  • 若在两个文件间需要共享同一变量,此时只能使用静态联编。

  • 若在两个文件间存在同名变量,且不能混淆,此时只能使用动态联编。

2.4、EL 表达式

EL,Expression Language,表达式语言,是一种在 JSP 页面中获取数据的简单方式。

EL表达式是从 JSP2.0 版本开始才引入的概念。

EL 表达式的基本语法形式很简单:在 JSP 页面的任何静态部分均可通过${expression}的形式获取到指定表达式的值。

2.4.1、获取数据

从四大域中依次查找数据

EL 只能从 pageConext、request、session、application 四大域属性空间中获取数据。

以下方式是无法获取到指定数据的。因为这个数据没有存放在四大域属性空间中。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第36张图片

此时,可以将这个值存放到四大域属性空间中的任意一个中。然后访问其存放时的 key即可。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第37张图片

我们发现,无论是将变量存放到了哪一个域属性空间,通过${key}的方式,均可访问到该数据的值。

到底是从哪个域空间中查找指定的 key 的呢?

其底层实际是从最小范围依次EL查找,直到查找到最大范围 application。这期间,只要查找到了,则直接获取,后面的域空间将不再查找。若最终没有查找到,s则什么也不输出。

缺点:依次寻找,执行效率低

从指定域中获取数据

从 pageContext 依次查找到 application 域空间,会降低执行效率。

若某属性确定存放在某个域属性空间,则可指定直接从该空间中查找。

此时需要借助 EL 的四个域属性空间相关的内置对象。

序号 内置对象 说明
1 pageScope 从 page 范围域属性空间中查找指定的 key
2 requestScope 从 request 范围域属性空间中查找指定的 key
3 sessionScope 从 session 范围域属性空间中查找指定的 key
4 applicationScope 从 application 范围域属性空间中查找指定的 key

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第38张图片

访问 Bean 的属性

EL 可以通过 ${key.属性} 的方式获取到指定对象的指定属性值。其底层实际调用的是该对象的相应属性的 get 方法。

当然,也可以使用 ${key[‘属性’]或${key[“属性”] 的方式获取。该方式不常用。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第39张图片

当然,若要访问一个对象的域属性的值,则可多次使用点号运算符,依次取出相应的属性值。

首先定义 School 类:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第40张图片

然后再定义 Student 类:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第41张图片

在 JSP 页面中访问:

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第42张图片

​ student 里的 school 里的 sname

获取数组中的元素

EL 可以通过 ${key[索引]}的方式获取到指定索引的元素。

不过,需要注意的是,若数组中不存在该指定索引的元素,系统并不会抛出数组越界异常。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第43张图片

获取 List 中的元素

与获取数组中的元素相同,通过 ${key[索引]}的方式可以获取 List 中指定索引的元素。

若 List 中不存在该指定索引的元素,系统并不会抛出越界异常。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第44张图片

不过,需要注意的是,EL 无法输出 Set 集合中的元素。因为 Set 集合中的元素具有无序性,即没有索引的概念。无法通过索引获取元素。

获取 Map 中的元素

EL 通过${attributeName.mapKey}的方式可以获取指定 Map 的指定 key 的值。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第45张图片

可以将 Object 自动强转成 String类型

2.4.2、运算符

EL 表达式可以进行各种运算,其中常用的运算符有:

序号 种类 预算符
1 计算运行符 + - * / % (不支持 ++、–)
2 关系运算符 == != > >= < <=
3 逻辑运算符 ! && || not and or
4 条件运算符 ? :
5 取值运算符 [] 点号.
<%@ page pageEncoding="UTF-8" import="com.bjpowernode.beans.*, java.util.*"%>




Insert title here


	
	<%
		String username = null;
		String schoolName = "";
		
		List students = new ArrayList<>(); 
		
		pageContext.setAttribute("username", username);
		pageContext.setAttribute("schoolName", schoolName);
		pageContext.setAttribute("students", students);
	%>
	
	
	empty name = ${empty name } 
empty username = ${empty username }
empty schoolName = ${empty schoolName }
empty students = ${empty students }
2.4.3、EL 内置对象

就像 JSP 的 Java 代码块及表达式块中可以使用九个内置对象一样,EL 表达式中,同样也存在有内置对象,并且存在 11 个内置对象。常用的内置对象,除了前面使用过的四个域属性空间相关的内置对象外,还有如下几个。

pageContext

该 pageContext 与 JSP 内置对象中的 pageContext 是同一个对象。通过该对象,可以获取到 request、response、session、servletContext、servletConfig 等对象。

注意,这些对象在 EL 中不是内置对象。这些对象只能通过 pageContext 获取。

在 EL 中直接${pageContext.request}即可获取 request 对象

当然,其底层实际调用的是pageContext.getRequest()方法。同理,也可以通过类似方式获取到其它对象。

在这些获取的对象中,有一个是实际工程中最常用的:

在这里插入图片描述

${pageContext.request.contextPath} ,用于获取当前项目的发布到服务器的名称,一般会用在 JSP 页面的路径前。

在 EL 的 11 个内置对象中,除了 pageContext 外,其它 10 个内置对象,其类型均为java.util.Map 类型。

param

在 EL 中通过 ${param.参数名}可获取到请求中指定参数名的值。 例如,提交的请求为:

在这里插入图片描述

在 JSP 页面中通过如下方式,可获取到 name 参数的值为 abc。

param.name = ${param.name} 

paramValues

若提交的请求中同一参数具有多个值,则可通过${paramValues.参数名[索引]}获取到指定索引号的该参数值。

例如,提交的请求为:

在这里插入图片描述

在 JSP 页面中获取方式如下:

bobby[0] = ${paramValues.hobby[0]} 
bobby[1] = ${paramValues.hobby[1]}

在浏览器中显示内容如下:

在这里插入图片描述

initParam

在 EL 中通过使用 ${initParam.初始化参数名} 可以获取到指定的初始化参数的值。例如,在 web.xml 中定义了初始化参数 xxxName。

JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第46张图片

在 JSP 的 EL 中可访问该初始化参数:

在这里插入图片描述

程序代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




Insert title here


	
	name = ${param.name } 
age = ${param.age }
hobby[0] = ${paramValues.hobby[0] }
hobby[1] = ${paramValues.hobby[1] }
hobby[2] = ${paramValues.hobby[2] }
company = ${initParam.company }
address = ${initParam.address }
2.4.4、自定义 EL 函数

EL 中存在一个问题:不支持字符串的操作

就连最简单的字符串连接,例如${“ab” + “cd”}都不支持,运行会报错。

更不要提将字符串中的字符转换为全大写、判断一个字符串中是否包含另一个子串等操作,EL 本身更是无法完成。

但 EL 支持自定义函数,可以在 EL 中调用自定义的函数来完成这些功能。

下面以实现“将一个字符串转换为全大写”功能为例,来讲解自定义 EL 函数的过程。

定义函数

定义一个 POJO 类,在该类中定义一个静态方法。该方法可以实现将字符串转换为全大写字母的功能。
JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第47张图片

注册函数

在 Web 项目的/WEB-INF 目录下,新建一个扩展名为.tld 的 XML 文件,例如 myfn.tld。

tld,即 Tag Library Definition,标签库定义。将定义好的函数,在这个文件中进行注册。

1、添加约束

XML 文件是需要在文件中添加相应约束的,即添加配置文件头部信息。

这个头部信息可以从 Tomcat 的 webapps 中的/examples/WEB-INF/jsp2/jsp2-example-taglib.tld 文件中复制。

这个 .tld 的XML 文件,需要定义在当前 Web 项目的 WEB-INF 目录下


2、添加其它子标签(标签库信息)

根标签下添加其它子标签。

在这里插入图片描述

  • 1.0

    指定定义的当前函数库版本号。随意指定。

  • myfn

    指定该函数库的名称,一个函数库一个名称,即一个 tld 文件一个。名称随意,但一般与文件名相同,这个名称在后面 JSP 中要使用。

  • http://www.xxx.com/jsp/myCustomTld

    指定该函数库所对应的 URL,一个函数库一个 URL,即一个 tld 文件一个 URL。 随意,URL在后面 JSP 中要使用该 URL。

3、注册函数

根标签的子标签下添加子标签,注册函数。

在这里插入图片描述

  • myLowerToUpper

    指定将来在 JSP 的 EL 中使用该函数的名称。一般与类中静态方法同名。

  • com.abc.functions.StringFunctions

    指定该函数定义在哪个类中。

  • java.lang.String lowerToUpper( java.lang.String )

    指定该函数的签名,即在指定类中的哪个方法,而且必须是全名。

4、整体配置
JavaWeb—JSP基础和系统开发模型—Eclipse版动力节点学习笔记_第48张图片

tld 代码


<taglib xmlns="http://java.sun.com/xml/ns/j2ee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
	version="2.0">
	
	
    <

你可能感兴趣的:(java)