4.3 EL隐式对象

JSP页面中,可以利用JSP脚本来访问JSP隐式对象。但是,在没有脚本的JSP页面中,则不可能访问这些隐式对象。不过类似JSP隐式对象,EL自己也提供了一组的隐式对象。EL隐式对象如下表所示:

对象 描述
pageContext 这是当前JSPjavax.servlet.jsp.PageContex类对象
initParam 这是一个包含所有环境初始化参数Map集合,使用参数名作为key
param 这是一个包含所有请求参数Map集合,使用参数名作为key。一个key只会返回第一个匹配的参数值.因此,如果两个请求参数同名,则只有第一个能够利用param获取到值。要想访问同名参数的所有参数值,就得用params代替
paramValues 这是一个包含所有请求参数Map集合,使用参数名作为key。每个key对应的值是一个字符串数组,数组中包含了指定参数名称的所有参数值。就算该参数只有一个值,它也仍然会返回一个只带有一个元素的数组
header 这是一个包含请求标题Map集合,使用标题名作为key。如果一个标题有多个值,则只返回第一个值。要想获得多个值,则应该使用headerValues对象
headerValues 这是一个包含请求标题Map集合,使用标题名作为key的。每个key对应的值是一个字符串数组,该数组中包含了指定标题名称的所有参数值。就算该标题只有一个值,它也仍然会返回一个只带有一个元素的数组
cookie 这是一个包含了当前请求对象中所有Cookie对象Map集合Cookie名称就是key,并且每个key都映射到一个Cookie对象
applicationScope 这是一个包含了**ServletContext对象中所有属性**的Map集合,使用属性名称作为key
sessionScope 这是一个包含了**HttpSession对象中所有属性**的Map集合,使用属性名称作为key
requestScope 这是一个包含了当前**HttpServletRequest对象中所有属性**的Map集合,使用属性名称作为key
pageScope 这是一个包含了整个页面范围内的所有属性Map集合。使用属性名称作为key

4.2 访问JavaBean

利用.[]运算符,都可以访问bean的属性,其结构如下:

1
2
${beanName["propertyName"]}
${beanName.propertyName}

例如,访问myBean secret属性,使用以下表达式:

1
${myBean.secret}

链式访问

如果该对象的属性是一个有属性的对象,那么同样可以继续使用.[]运算符来访问这个作为属性的对象的属性。

4.1.2 []和.运算符

EL表达式可以返回任意类型的值。如果EL表达式的结果是一个带有属性的对象,则可以利用[ ]或者.运算符来访问对象的属性。“[ ]”和“.”运算符类似;“[ ]”是比较规范的形式,“.”运算符则比较快捷。

EL表达式如何访问对象的属性

为了访问对象的属性,可以使用以下任意一种形式:

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

但是,如果propertyName不是有效的Java变量名,只能使用[ ]运算符。例如,下面这两个EL表达式就可以用来访问隐式对象标题中的HTTP标题host

1
2
${header["host"]}
${header.host}

但是,要想访问accept-language标题,则只能使用“[ ]”运算符,因为accept-language不是一个合法的Java变量名。如果用“.”运算符访问它,将会导致异常。

当表达式中对象的属性也是对象的情况 EL链式访问

对象的属性也是对象的情况,如何访问属性对象中的属性,要想访问属性对象的属性,这个时候就需要嵌套使用运算符了。
例如,隐式对象pageContext是表示当前JSPPageContext对象。它有request属性,表示HttpServletRequest类的对象。而HttpServletRequest又带有servletPath属性。下列几个表达式的结果相同,均能得出pageContext对象的中HttpServletRequest对象中的servletPath属性值:

1
2
3
4
${pageContext["request"]["servletPath"]}
${pageContext.request["servletPath"]}
${pageContext.request.servletPath}
${pageContext["request"].servletPath}

要访问HttpSession,可以使用以下语法:

1
${pageContext.session}

例如,以下表达式会得出session标识符:

1
${pageContext.session.id}

4.1.3 EL表达式取值规则

EL表达式的取值是从左到右进行的。对于expression-a[expression-b]这种形式的表达式,其意思是根据expression-bexpression-a中取出数据,具体来说EL表达式的取值规则如下:

  • 先计算expression-a得到value-a
  • 如果value-anull,从null里面是无法取出什么值,所以直接返回null
  • 如果value-a不为null,则继续计算expression-b得到value-b
  • 如果value-bnullvalue-a中取出null,这也是不对的,所以直接返回null
  • 如果value-ajava.util.Map,则表达式的意思是,value-a这个Map集合中取出keyvalue-b的值.那么检查value-b是否为Map中的一个key
    • 如果是key,则根据keyMap中取出一个值,也就是返回value-a.get(value-b)的结果。
    • 如果不是key,那自然取不到对应的值,将返回null
  • 如果value-ajava.util.List,则这个的表达式的意思是value-a这个List集合中取出下标为value-b的值
    • 下标都是int类型的,所以首先把value-b强制转换为int类型,如果强制转换失败,则抛出异常。
    • 如果强制类型转换为int类型成功,但是value-a.get(value-b)抛出IndexOutOfBoundsException异常,则返回null
    • 如果强制转换为int类型成功,并且不抛出IndexOutOfBoundsException异常,返回value-a.get(value-b)的结果,也就是返回value-a这个List集合中下标为value-b的值.
  • 如果value-a是一个Array,那么表达式的意思是:value-a这个Array集合中取出下标为value-b的数据,则要进行以下处理:
    • 首先把value-b强制转换为int类型,如果强制转换失败,则抛出异常。
    • 假如Array.get(value-a, value-b)抛出ArrayIndexOutOfBoundsException,则返回null
    • 以上没问题的话则返回Array.get(value-a, value-b)的值.也就是返回value-a这个Array集合中下标为value-b的数据
  • 如果value-a不是一个MapList或者 array,那么,value-a必须是一个JavaBean,此时表达式的意思是:从value-a对象中取出属性名称为value-b的属性的属性值
    • 首先强制转换value-bString类。如果value-bvalue-a对象的一个可读属性,则要调用该属性的getter方法从value-a对象中取出属性值。
    • 如果getter方法抛出异常,该表达式就是无效的,
    • 否则,该表达式有效。

4.1 表达式语言的语法

EL表达式的语法格式

EL表达式以${开头,并以 } 结束。EL表达式的结构如下:

1
${expression}

EL表达式的数学运算

例如,表达式x+y,可以写成:

1
${x+y}

首尾相连的EL表达式将进行字符串连接操作

对于两个首尾相连的EL表达式,先从左到右计算各个表达式,并将每个表达式的计算结果都转成String类型,然后各个结果连接到一起就得到了最终的结果。
例如

1
${a+b}${c+d}

假设,上面的a+b等于8c+d等于10,那么这两个表达式的计算结果将是8 1 0.
同理,表达式${a+b}and${c+d}的取值结果则是8and10

第4章 表达式语言 概述

JSP 2.0最重要的特性之一就是表达式语言(ELJSP用户可以使用EL来访问应用程序的数据。使用EL可以轻松地编写无脚本的JSP页面。也就是说,在JSP页面中可以不使用任何JSP声明JSP表达式或者JSP脚本,只需要使用EL即可。

3.8 小结

JSP是构建Java Web应用程序的第二种技术,是Servlet技术的补充,一个精心设计的Java Web应用程序会同时使用ServletJSP两种技术。
在本章中,我们已经学到了JSP是如何工作的,以及如何编写JSP页面。现在,我们已经知道JSP的隐式对象,并能在JSP页面中使用3个语法元素:指令脚本动作

3.7 错误处理

错误处理页面有什么用

JSP提供了很好的错误处理能力。除了在Java代码中可以使用try语句捕捉异常之外,JSP中还可以指定一个特殊的页面进行异常处理。这样当应用页面遇到try语句没有捕获到的异常的时候,用户就可以看到一个精心设计的异常处理页面,该页面向用户解释发生了什么,而不是显示一个用户无法理解的错误信息。

如何设置一个错误处理页面

要想把一个JSP页面设置为错误页面,只要把page指令的isErrorPage属性设置为true即可。

实例

errorHandler.jsp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@page isErrorPage="true"%>
<!DOCTYPE html>
<html>
<head>
<title>错误处理页面</title>
</head>
<body>
发生了一个错误
<br />错误信息:
<%
out.println(exception.toString());
%>
</body>
</html>

如何在其他页面指定要进行错误处理的页面

在其他页面,把page指令的errorPage属性设置为上面的错误处理页面即可。这样如果该页面产生了错误,错误将由错误处理页面进行处理,而不是将错误打印到服务器控制台中。

实例

pageHasError.jsp:

1
2
3
4
5
6
7
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@page errorPage="errorHandler.jsp"%>
<h2>生成一个错误</h2>
<%
Integer.parseInt("Throw me");
%>

访问pageHasError.jsp页面,将显示如下:
这里有一张图片
可以看到浏览器显示的是errorHandler.jsp页面的内容,查看服务器控制台,我们将不会看到错误信息.

3.6.4 forward动作

forward动作将当前请求转发到其他web资源,例如将请求转发到其他JSP页面之中

实例

jspForwardTest.jsp:

1
2
3
4
5
6
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%--重定向到login.jsp页面 --%>
<jsp:forward page="login.jsp">
<jsp:param name="text" value="please let me in" />
</jsp:forward>

login.jsp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
String text=request.getParameter("text");
out.print("收到text参数,值为:"+text);
%>
</body>
</html>

访问jspForwardTest.jsp,显示效果如下:
这里有一张图片
可以看到当请求jspForwardTest.jsp这个JSP页面是,它将请求转发到了login.jsp页面,并传递了一个参数.