JSP梳理
2012-04-20
定位:
- JSP文件的基本结构和语法;
- 常用场景的说明;
简介
JSP最终会生成servlet,在之前的博客中有介绍;JSP页面的几个特点:
- JSP编写页面,用于负责显示;
- JSP页面中,可以添加java代码;
- JSP页面提供丰富的标签;
JSP 页面处理过程
Web服务器,是如何利用JSP来创建动态网页的?(参考下图)
- 服务器收到是JSP页面请求,转发给JSP引擎;(JSP页面请求:由URL或.jsp文件来标识)
- JSP引擎,进行预处理:将JSP页面生成为java代码;
- JSP引擎,将java文件编译为class文件;
- 编译后的class文件被加载到容器中,根据用户请求生成HTML格式的响应页面;
本质上,执行JSP页面,分为两个阶段:
- 翻译阶段:Translation phase,JSP页面被翻译为Servlet类(java文件),然后编译为class文件;
- 请求阶段:Request phase,class文件被加载执行后,响应前端的请求;
本质上,JSP页面抽取了Servlet中包含的HTML标签信息(out.write(“…html…”)),简化了Servlet的编写。
JSP引擎会检查JSP文件修改日期与Servlet的修改日期,如果JSP没有修改,则Servlet一直有效,即,只进行一次Servlet编译(翻译阶段只进行一次)。JSP和Servlet的执行速度是一样的。
JSP 生命周期
理解JSP底层功能的关键就是去理解它们所遵守的生命周期。
JSP生命周期就是从创建到销毁的整个过程,类似于servlet生命周期,区别在于JSP生命周期还包括将JSP文件编译成servlet。
以下是JSP生命周期中所走过的几个阶段:
- 编译阶段:servlet容器编译servlet源文件,生成servlet类
- 初始化阶段:加载与JSP对应的servlet类,创建其实例,并调用它的初始化方法
- 执行阶段:调用与JSP对应的servlet实例的服务方法
- 销毁阶段:调用与JSP对应的servlet实例的销毁方法,然后销毁servlet实例
很明显,JSP生命周期的四个主要阶段和servlet生命周期非常相似,下面给出图示:
JSP编译
当浏览器请求JSP页面时,JSP引擎会首先去检查是否需要编译这个文件。如果这个文件没有被编译过,或者在上次编译后被更改过,则编译这个JSP文件。
编译的过程包括三个步骤:
- 解析JSP文件
- 将JSP文件转为servlet
- 编译servlet
JSP初始化
容器载入JSP文件后,它会在为请求提供任何服务前调用jspInit()
方法。如果您需要执行自定义的JSP初始化任务,复写jspInit()
方法就行了,就像下面这样:
public void jspInit(){
// 初始化代码
}
一般来讲程序只初始化一次,servlet也是如此。通常情况下您可以在jspInit()方法中初始化数据库连接、打开文件和创建查询表。
JSP执行
这一阶段描述了JSP生命周期中一切与请求相关的交互行为,直到被销毁。
当JSP网页完成初始化后,JSP引擎将会调用_jspService()
方法。
_jspService()
方法需要一个HttpServletRequest对象和一个HttpServletResponse对象作为它的参数,就像下面这样:
void _jspService(HttpServletRequest request,
HttpServletResponse response)
{
// 服务端处理代码
}
_jspService()
方法在每个request中被调用一次并且负责产生与之相对应的response,并且它还负责产生所有7个HTTP方法的回应,比如GET、POST、DELETE等等。
JSP清理
JSP生命周期的销毁阶段描述了当一个JSP网页从容器中被移除时所发生的一切。
jspDestroy()
方法在JSP中等价于servlet中的销毁方法。当您需要执行任何清理工作时复写jspDestroy()
方法,比如释放数据库连接或者关闭文件夹等等。
jspDestroy()
方法的格式如下:
public void jspDestroy()
{
// 清理代码
}
实例
JSP生命周期代码实例如下所示:
<%@ page contentType="text/html; charset=GB2312" %>
<html><head><title>life.jsp</title></head><body>
<%!
private int initVar=0;
private int serviceVar=0;
private int destroyVar=0;
%>
<%!
public void jspInit(){
initVar++;
System.out.println("jspInit(): JSP被初始化了"+initVar+"次");
}
public void jspDestroy(){
destroyVar++;
System.out.println("jspDestroy(): JSP被销毁了"+destroyVar+"次");
}
%>
<%
serviceVar++;
System.out.println("_jspService(): JSP共响应了"+serviceVar+"次请求");
String content1="初始化次数 : "+initVar;
String content2="响应客户请求次数 : "+serviceVar;
String content3="销毁次数 : "+destroyVar;
%>
<h1><%=content1 %></h1>
<h1><%=content2 %></h1>
<h1><%=content3 %></h1>
</body></html>
思考:上述代码中,为什么要使用<%! .. %>
,其中!
的含义?
JSP 语法
脚本程序(可执行代码)
脚本程序可以包含任意量的Java语句、变量、方法或表达式,只要它们在脚本语言中是有效的。
- 脚本程序的语法格式:
<% 代码片段 %>
; - 任何文本、HTML标签、JSP元素必须写在脚本程序的外面;
JSP声明
一个声明语句可以声明一个或多个变量、方法,供后面的Java代码使用。在JSP文件中,您必须先声明这些变量和方法然后才能使用它们。
JSP声明的语法格式:
<%! declaration; [ declaration; ]+ ... %>
JSP表达式
一个JSP表达式中包含的脚本语言表达式,先被转化成String,然后插入到表达式出现的地方。
由于表达式的值会被转化成String,所以您可以在一个文本行中使用表达式而不用去管它是否是HTML标签。
表达式元素中可以包含任何符合Java语言规范的表达式,但是不能使用分号来结束表达式。
JSP表达式的语法格式:
<%= 表达式 %>
JSP注释
JSP注释主要有两个作用:为代码作注释以及将某段代码注释掉。
JSP注释的语法格式:
<%-- 这里可以填写 JSP 注释 --%>
不同情况下使用注释的语法规则:
语法 | 描述 |
---|---|
<%-- 注释 --%> |
JSP注释,注释内容不会被发送至浏览器甚至不会被编译 |
<!-- 注释 --> |
HTML注释,通过浏览器查看网页源代码时可以看见注释内容 |
JSP指令
JSP指令用来设置与整个JSP页面相关的属性。
JSP指令语法格式:
<%@ directive attribute="value" %>
这里有三种指令标签:
指令 | 描述 |
---|---|
<%@ page ... %> |
定义页面的依赖属性,比如脚本语言、error页面、缓存需求等等 |
<%@ include ... %> |
包含其他文件 |
<%@ taglib ... %> |
引入标签库的定义,可以是自定义标签 |
Page指令
Page指令为容器提供当前页面的使用说明。一个JSP页面可以包含多个page指令。
Page指令的语法格式:
<%@ page attribute="value" %>
属性
下表列出与Page指令相关的属性:
属性 | 描述 |
---|---|
buffer | 指定out对象使用缓冲区的大小 |
autoFlush | 控制out对象的 缓存区 |
contentType | 指定当前JSP页面的MIME类型和字符编码 |
errorPage | 指定当JSP页面发生异常时需要转向的错误处理页面 |
isErrorPage | 指定当前页面是否可以作为另一个JSP页面的错误处理页面 |
extends | 指定servlet从哪一个类继承 |
import | 导入要使用的Java类 |
info | 定义JSP页面的描述信息 |
isThreadSafe | 指定对JSP页面的访问是否为线程安全 |
language | 定义JSP页面所用的脚本语言,默认是Java |
session | 指定JSP页面是否使用session |
isELIgnored | 指定是否执行EL表达式 |
isScriptingEnabled | 确定脚本元素能否被使用 |
pageEncoding | 设定JSP页面编码方式 |
Include指令
JSP可以通过include指令来包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。包含的文件就好像是该JSP文件的一部分,会被同时编译执行。
Include指令的语法格式如下:
<%@ include file="relative url" %>
Taglib指令
JSP API允许用户自定义标签,一个自定义标签库就是自定义标签的集合。
Taglib指令引入一个自定义标签集合的定义,包括库路径、自定义标签。
Taglib指令的语法:
<%@ taglib uri="uri" prefix="prefixOfTag" %>
uri属性确定标签库的位置,prefix属性指定标签库的前缀。
JSP 动作元素
与JSP指令元素不同的是,JSP动作元素在请求处理阶段
起作用(还有一个阶段:翻译阶段)。它能够动态插入一个文件,重用JavaBean组件,引导用户去另一个页面,为Java插件产生相关的HTML等等。
行为标签只有一种语法格式,它严格遵守XML标准:
<jsp:action_name attribute="value" />
行为标签基本上是一些预先就定义好的函数,下表罗列出了一些可用的JSP行为标签::
语法 | 描述 |
---|---|
jsp:include |
用于在当前页面中包含静态或动态资源 |
jsp:useBean |
寻找和初始化一个JavaBean组件 |
jsp:setProperty |
设置 JavaBean组件的值 |
jsp:getProperty |
将 JavaBean组件的值插入到 output中 |
jsp:forward |
从一个JSP文件向另一个文件传递一个包含用户请求的request对象 |
jsp:plugin |
用于在生成的HTML页面中包含Applet和JavaBean对象 |
jsp:element |
动态创建一个XML元素 |
jsp:attribute |
定义动态创建的XML元素的属性 |
jsp:body |
定义动态创建的XML元素的主体 |
jsp:text |
用于封装模板数据 |
JSP隐含对象
JSP支持 9 个隐含对象,又称预定义变量,即,JSP容器为每个页面提供的Java对象,可直接使用:
对象 | 描述 |
---|---|
request | HttpServletRequest类的实例 |
response | HttpServletResponse类的实例 |
out | PrintWriter类的实例,用于把结果输出至网页上 |
session | HttpSession类的实例 |
application | ServletContext类的实例,与应用上下文有关 |
config | ServletConfig类的实例 |
pageContext | PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问 |
page | 类似于Java类中的this关键字 |
Exception | Exception类的对象,代表发生错误的JSP页面中对应的异常对象 |
Todo:
- 单独写一篇,内置对象的使用和简介;
- spring mvc使用过程中,是否设计这些对象?
常见问题
jsp中插入java代码
插入java代码方式如下:<% ... %>
,例如:
<body>
<% out.pringln("Hello World!"); %>
</body>
参考来源
- JavaServet Pages 官方规范-JSR245
- JSP-tutorial (大部分内容,来自此处)
原文地址:https://ningg.top/jsp-intro/