JSP+EL表达式
课程大纲:
1、Jsp概述与执行原理
2、Jsp基本语法
3、Jsp指令
4、Jsp的内置对象和域对象(重点)
5、Jsp最佳实践
6、EL表达式(非常重要)
学习目标:了解Jsp的运行机制,掌握jsp内置对象和域对象的使用以及EL的基本使用
1 JSP概述与执行原理
1.1 Jsp概述
JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。
JSP这门技术的最大的特点在于,写jsp就像在写html,但:
Ø 它相比html而言,html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据。
Ø 相比servlet而言,servlet很难对数据进行排版,而jsp除了可以用java代码产生动态数据的同时,也很容易对数据进行排版。
Jsp快速入门:在jsp页面中输出当前时间。
比较servlet开发和JSP开发:
不管是JSP还是Servlet,虽然都可以用于开发动态web资源。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。
其原因为,程序的数据通常要美化后再输出:
Ø 让jsp既用java代码产生动态数据,又做美化会导致页面难以维护。
Ø 让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。
因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做。
1.2 Jsp执行原理
在tomcat中找到JSP引擎动态产生的文件
理解JSP引擎工作原理
1)首先,客户端发出请求(request ),请求访问JSP网页
2)接着,JSP Container将要访问的.JSP文件 转译成Servlet的源代码(.java文件)
3)然后,将产生的Servlet的源代码(.java文件)经过编译,生成.class文件,并加载到内存执行
4)最后把结果响应(response )给客户端
2 Jsp基本语法
2.1 JSP模板元素
JSP页面中的HTML内容称之为JSP模版元素。
JSP模版元素定义了网页的基本骨架,即定义了页面的结构和外观。
2.2 JSP脚本表达式
JSP脚本表达式(expression)用于将程序数据输出到客户端
语法:<%= 变量或表达式 %>
举例:当前时间:<%= new java.util.Date() %>
JSP引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应位置用out.write(…) 将数据输给客户端。
JSP脚本表达式中的变量或表达式后面不能有分号(;)。
2.3 JSP脚本片段
JSP脚本片断(scriptlet)用于在JSP页面中编写多行Java代码。语法:
<%
多行java代码
%>
注意:JSP脚本片断中只能出现java代码,不能出现其它模板元素, JSP引擎在翻译JSP页面中,会将JSP脚本片断中的Java代码将被原封不动地放到Servlet的_jspService方法中。
JSP脚本片断中的Java代码必须严格遵循Java语法,例如,每执行语句后面必须用分号(;)结束。
在一个JSP页面中可以有多个脚本片断,在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他JSP元素。
举例:
<%
int x = 10;
out.println(x);
%>
<p>这是JSP页面文本</p>
<%
int y = 20;
out.println(y+””+x);
%>
多个脚本片断中的代码可以相互访问,犹如将所有的代码放在一对<%%>之中的情况。如:out.println(x);
单个脚本片断中的Java语句可以是不完整的,但是,多个脚本片断组合后的结果必须是完整的Java语句,例如:
<%
for (int i=1; i<5; i++)
{
%>
<H1>www.itcast.cn</H1>
<%
}
%>
2.4 JSP声明
JSP页面中编写的所有代码,默认会翻译到servlet的service方法中, 而Jsp声明中的java代码被翻译到_jspService方法的外面,即实例变量。语法:
<%!
java代码
%>
所以,JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法 。
多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明中。
JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式对象。
<%!
static
{
System.out.println("loading Servlet!");
}
private int globalVar = 0;
public void jspInit()
{
System.out.println("initializing jsp!");
}
%>
<%!
public void jspDestroy()
{
System.out.println("destroying jsp!");
}
%>
2.5 JSP注释
JSP注释的格式:
<%-- 注释信息 --%>
JSP引擎在将JSP页面翻译成Servlet程序时,忽略JSP页面中被注释的内容。
3 Jsp指令
JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。在JSP 2.0规范中共定义了三个指令:
page指令
Include指令
taglib指令
3.1指令基本语法
JSP指令的基本语法格式:
<%@ 指令 属性名="值" %>
举例:<%@ page contentType="text/html;charset=UTF-8"%>
如果一个指令有多个属性,这多个属性可以写在一个指令中,也可以分开写。
例如:
<%@ page contentType="text/html;charset=UTF-8"%>
<%@ page import="java.util.Date"%>
也可以写作:
<%@ page contentType="text/html;charset=UTF-8" import="java.util.Date"%>
3.2 Page指令
page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
page指令的属性:
language="指明JSP支持的语言,默认为java语言"
*import="当前JSP页面中,需要导入的包,其中import可以写多次"
session="true表示需要服务器创建session/false不需要服务器创建session",默认true
buffer="none|8kb|sizekb"JSP输出使用的缓存大小,默认8kb
autoFlush="true表示当缓存满时,web容器是自动刷新到客户端/false需要手工刷新到客户端",默认true
isThreadSafe="true表示web服务器确保线程安全/false不确保线程安全",默认true
info="text"表示jsp的相关描述信息,可以通过getServletInfo()取得该jsp的信息
*errorPage="当前jsp页面出错后,转发到的目标页面"
*isErrorPage="true"(当某个jsp页面有该属性时,web容器会自动创建exception对象
使用page指令解决JSP中文乱码:
JSP程序存在有与Servlet程序完全相同的中文乱码问题
Ø 输出响应正文时出现的中文乱码问题
Ø 读取浏览器传递的参数信息时出现的中文乱码问题
JSP引擎将JSP页面翻译成Servlet源文件时也可能导致中文乱码问题(UTF-8)
===如何解决JSP引擎翻译JSP页面时的中文乱码问题=====
1)通过page指令的contentType属性说明JSP源文件的字符集编码
2)page指令的pageEncoding属性说明JSP源文件的字符集编码
3.3 Include指令
include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为静态引入。
语法:
<%@ include file="relativeURL"%>
其中的file属性用于指定被引入文件的相对路径。 file属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前文件。
细节:
Ø 被引入的文件必须遵循JSP语法。
Ø 被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments)作为静态引入文件的扩展名。
Ø 由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外)。
4 JSP 9个隐藏对象和4个域对象
4.1 什么是隐含对象?
不用我们手工去创建的对象,由容器根据页面设置而产生直接可以使用
request HttpServletRequest
response HttpServletResponse
session HttpSession
application ServletcContext
config ServletConfig
exception (特殊情况下使用)
page this(本JSP页面)
out JspWriter(带缓冲的PrintWriter)
pageContext (使普通Java类可访问WEB资源,自定义标签常用)
4.2 out隐藏对象
out隐式对象用于向客户端发送文本数据。
out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
设置page指令的buffer属性关闭了out对象的缓存功能
Ø out对象的缓冲区已满
Ø 整个JSP页面结束
out隐式对象的工作原理图
4.3 pageContext对象
pageContext对象是JSP技术中最重要的一个对象,它代表当前JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象,可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如包含和跳转其它资源、检索其它域对象中的属性等。
通过pageContext获得其他对象
getException方法返回exception隐式对象
getPage方法返回page隐式对象
getRequest方法返回request隐式对象
getResponse方法返回response隐式对象
getServletConfig方法返回config隐式对象
getServletContext方法返回application隐式对象
getSession方法返回session隐式对象
getOut方法返回out隐式对象
pageContext封装其它8大内置对象的意义。
pageContext作为域对象
pageContext对象的方法
Ø public void setAttribute(java.lang.String name,java.lang.Object value)
Ø public java.lang.Object getAttribute(java.lang.String name)
Ø public void removeAttribute(java.lang.String name)
pageContext对象中还封装了访问其它域的方法
Ø public java.lang.Object getAttribute(java.lang.String name,int scope)
Ø public void setAttribute(java.lang.String name, java.lang.Object value,int scope)
Ø public void removeAttribute(java.lang.String name,int scope)
代表各个域的常量
Ø PageContext.APPLICATION_SCOPE
Ø PageContext.SESSION_SCOPE
Ø PageContext.REQUEST_SCOPE
Ø PageContext.PAGE_SCOPE
findAttribute方法 (*重点,先后查找各个域中的属性)
4.4 四大域对象
到此为止,web开发接触到了4个域对象:
Ø pageContext(称之为page域)
Ø request(称之为request域)
Ø session(称之为session域)
Ø servletContext(称之为application域)
这4个域对象是学习web的重点,也是笔试经常考察的知识点。
明确如下问题:
Ø 这4个对象的生命周期?
Ø 什么是域?为什么把这4个对象叫做域对象呢?
Ø 哪种情况下用哪种域对象。
引入和跳转到其他资源
PageContext类中定义了一个forward方法和两个include方法来分别简化和替代RequestDispatcher.forward方法和include方法
传递给这些方法的资源路径,如果路径以“/”开头,表示相对于当前WEB应用程序的根目录,否则,表示相对于当前JSP所映射到的访问路径。
5 Jsp最佳实践
不管是JSP还是Servlet,虽然都可以用于开发动态web资源。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。
其原因为,程序的数据通常要美化后再输出:
l 让jsp既用java代码产生动态数据,又做美化会导致页面难以维护。
l 让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。
l 因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做。
6 EL表达式
6.1 EL表达式概述
EL表达式语言是JSP2.0才引入的
Ø 补充jsp对Java Bean访问的能力
Ø 可以说是对useBean, getProperty, setProperty等动作的增强
语法
Ø 文字
Ø 运算符
Ø 变量和JavaBean属性数据输出
Ø 存取器
Ø 隐含对象
可以自由设置是否支持表达式语言
6.2 EL表达式语法
语法形式
${}
例如:
<jsp:useBean id=“boy”, class=“com.pojo.Boy”/>
${boy}
${boy.name}
在 EL 表达式中,数字、字符串、布尔值和 null 都可以被指定为文字值(常量)。字符串可以用单引号或双引号定界。布尔值被指定为 true 和 false 。
${100} | 100 |
${-168.18} | -168.18 |
${3.8E18} | 3.8E18 |
${3.8e-18} | 3.8e-18 |
${3.14159265} | 3.14159265 |
${"Hello JSP EL!"} | Hello JSP EL! 等价于 <%="Hello JSP EL!"%> |
${'Hello JSP EL...'} | Hello JSP EL... |
${true}//can be TRUE? | true |
${false}//can be FALSE? | false |
${str==null} | true |
6.3 EL 运算符
算术运算符
+、-、*、/(或 div)和 %(或 mod)
关系运算符
==(或 eq)、!=(或 ne)、<(或 lt)
>(或 gt)、<=(或 le)和>=(或 ge)
逻辑运算符
&&(或 and)、||(或 or)和 !(或 not)
验证运算符
empty
其中,empty 判断一个变量是否为null或是否包含有效数据:
if(name==null||name.equlas("")){…}
等价于
${empty name} -> true
存取器
[]
输出对象属性值,输出数组或集合中对应索引值
.
输出对象属性值
例子:
对象
列表
Map容器
6.4 EL中的隐含对象
EL提供了自己的一套隐含对象,方便在页面内对各种常用数据信息的访问.
EL隐藏对象 | JSP隐藏对象 |
pageScope/pageContext | pageContext |
requestScope | request |
sessionScope | session |
applicationScope | appication |
param | request.getParameter() |
paramValues | 在提交表单里,有多个输入域同名getParameterValues |
header | request.getHeader(), 按照key value的形式取出 value:是一个String类型的值 |
headerValues | 按照key value的方式取出, 但headerValues里面的value是一个String类型的数组 |
cookie | request.getCookies() |
initParam | context param |
EL表达式的支持
可以自由设置是否支持表达式语言,
<%@page isELIgnored="false"%> :
缺省为false,表示可以使用EL
配置web.xml也可达到同样的效果(同时存在,那种起作用?)(禁用脚本和EL) 默认都是false
在页面中通过page指令设置isELIgnored属性的优先级比在web.xml中通过<el-ignored>设置的高