EL表达式

EL表达式

在JSP开发中,为了获取Servlet域对象中存储的数据,经常需要书写很多Java代码,这样的做法会使JSP页面混乱,难以维护,为此,在JSP2.0规范中提供了EL表达式。EL是Expression Language的缩写,它是一种简单的数据访问语言。

初识EL

由于EL可以简化JSP页面的书写,因此,在JSP学习中,掌握EL是相当重要的,要使用EL表达式,首先要学习它的语法。EL表达式的语法非常简单,都是以"${“开始,以”}"符号结束。

${}

需要注意的是,${}中的表达式必须符合EL语法要求。

EL语法

EL中的标识符

在EL表达式中,经常需要使用一些符号来标记一些名称,如变量名、如变量名、自定义函数名等,这些符号被称为标识符。EL表达式中的标识符可以由任意顺序的大小写字母、数字和下划线组成,为了避免出现非法的标识符,在定义标识符时还需要遵循以下规范:
1)不能以数字开头;
2)不能是EL中的保留字,如and、or、gt;
3)不能是EL隐式对象,如pageContext;
4)不能包含单引号(’),双引号(")、减号(-)和正斜线等特殊字符。

EL中的保留字

and eq gt true instanceof
or ne le false empty
not lt ge null div mod

EL中的变量

EL表达式中的变量就是一个基本的存储单元,EL表达式可以将变量映射到一个对象上

${product}

在上述示例中,product就是一个变量。EL表达式中的变量不用事先定义就可以直接使用,例如,表达式${product}就可以访问变量product的值。

EL中的常量

EL表达式中的常量又称字面量,它是不能改变的数据。在EL表达式包括多种常量
布尔常量
true和false
整数常量
整数常量与Java中的十进制的整数常量相同,它的取值范围是Java语言中定义的常量Long.MIN_VALUE到Long.MAX_VALUE之间,即(-2)62~262-1之间的整数。
浮点数常量
浮点数用整数部分加小数部分表示,也可以指数形式表示,例如,1.2E4和1.2都是合法的浮点数常量。它的取值范围是Java语言中定义的常量Double.MIN_VALUE到Double.MAX_VALUE之间,即4.9E-324~1.8E308之间的整数。
字符串常量
字符串常量是用单引号或双引号引起来的一连串字符。由于字符串常量。由于字符串常量需要用单引号或双引号引起来,所以字符串本身包括的单引号和双引号需要用反斜线(\)进行转义。
Null常量
Null常量用于表示变量引用的对象为空,它只是一个值,用null表示。

EL中的运算符

EL表达式支持简单的运算,例如,加(+)、减(-)、乘(*)、除(/)等。为此,在EL中提供了多种运算符,根据运算方法的不同,EL中的运算符包括以下几种。
1、点运算符(.)
EL表达式中的点运算符,用于访问JSP页面中某些对象的属性,如JavaBean对象、List对象、Array对象等,其语法格式如下

${customer.name}

在上述语法格式中,表达式${customer.name}中点运算符的作用就是访问customer对象中的name属性。
2、方括号运算符([])
与点运算的功能相同,都用于访问JSP页面中某些对象的属性,当获取的属性名中包含一些特殊字符,如"-“或”?"等非字母或数字的符号,就只能使用方括号运算符来访问该属性。

${user["name"]}

需要注意的是,在访问对象的属性时,通常情况都会使用点运算符作为简单的写法,但,实际上方括号运算符比点运算符应用的更广泛。
方括号运算符可以访问List集合或数组中指定索引的某个元素,如表达式${user[0]}用于访问集合或数组中的第一个元素。这种情况下,只能使用方括号运算符,而不能使用点运算符。

3、算数运算符
EL表达式中的算数运算符用于对整数和浮点数的值进行算数运算。使用这些算数运算符可以非常方便地在JSP页面进行算术运算,并且可以简化页面地代码量。
4、比较运算符

EL表达式中的比较运算符用于比较两个操作数的大小,操作数可以是各种常量、EL变量或EL表达式,所有的运算符执行的结果都是布尔类型。
5、逻辑运算符
EL表达式中的逻辑运算用于结果为布尔类型的表达式进行运算,运算的结果仍为布尔类型。
6、empty运算符
EL表达式中的empty运算符用于判断某个对象是否为null为"",结果为布尔类型

${empty var}

需要注意的是,empty运算符可以判断变量是否为null或""。例如,下列情况empty运算符的返回值为true。
1)var变量不存在,即没有定义,例如表达式${empty name},如果不存在name变量,就返回true。
2)var变量的值为null,例如表单式${empty customer.name},如果不存在cutomer.name的值为null,就返回true。
3)var变量引用集合(Set、Map和List)类型对象,并且在集合对象中不包含任何元素。
7、条件运算符
EL表达式中条件运算符用于执行某种条件判断

${A?B:C}

8、()运算符
EL表达式中的圆括号用于改变其他运算符的优先级,例如表达式${ab+c},正常情况下会先计算ab的积,然后再将计算的结果与c相加,如果在这个表达式中加一个圆括号运算符,将表达式修改为${a*(b+c)},这样则先计算b与c的和,再将计算的结果与a相乘。

注:再EL表达式取值时,没有数组的下标越界,没有空指针异常,没有字符串拼接。

EL隐式对象

隐式对象名称描述
pageContext对应于JSP页面中的pageContext对象
pageScope代表page域中用于保存属性的Map对象
requestScope代表request域中用于保存属性的Map对象
sessionScope代表session域中用于保存属性的Map对象
applicationScope代表applicationScope域中用于保存属性的Map对象
param代表一个保存了所有请求参数的Map对象
paramValues表示一个保存了所有请求参数的Map对象,它对于某个请求参数,返回的是一个string类型数组
header表示一个保存所有http请求头字段的Map对象
headerValues表示一个保存了所有http请求头字段的Map对象,返回string类型数组
cookie用来取得使用者的cookie值,cookie的类型是Map
initParam表示一个保存了所有Web应用初始化参数的Map对象

pageContext可以获取其他10个隐式对象。

pageContext对象

为了获取JSP页面的隐式对象,可以使用EL表达式中的pageContext隐式对象。pageContext隐式对象的示例代码如下

${pageContext.reponse.characterEncoding}

上述实例中,pageContext对象用于获取response对象中的characterEncoding属性
pageContext.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
请求URL为:${pageContext.request.requestURI }<br>
<%=((HttpServletRequest)pageContext.getRequest()).getRequestURL() %><br>
Context-Type响应头:${pageContext.response.contentType }<br>
<%=((HttpServletResponse)pageContext.getResponse()).getContentType() %><br>
服务器信息为:${pageContext.servletContext.serverInfo }<br>
<%=pageContext.getServletContext().getServerInfo() %><br>
Servlet注册名为:${pageContext.servletConfig.servletName }<br>
<%=pageContext.getServletConfig().getServletName() %><br>
</body>
</html>

在这里插入图片描述
需要注意的是,不要将EL表达式和JSP中的隐式对象搞混,只有pageContext对象是两者共有的。

Web域相关对象

在Web开发中,PageContext、HttpServletRequest、HttpSession、ServletContext这四个对象之所以可以存储数据,是因为他们内部都定义了一个Map集合,这些Map集合是有一定作用范围的。习惯性地,我们把这些Map集合称为域,这些Map集合所在地对象称为域对象。

${pageScope.username}
${requestScope.username}
${sessionScope.username}
${applicationScope.username}

需要注意地是EL表达式只能在这4个作用域中获取数据。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
	session.setAttribute("st3", "session");
	request.setAttribute("st2", "request");
	pageContext.setAttribute("st1", "page");
	application.setAttribute("st4", "application");
	String st5="self";
	session.setAttribute("st6", "session");
	request.setAttribute("st6", "request");
	pageContext.setAttribute("st6", "page");
	application.setAttribute("st6", "application");
%>
${st1 }
${pageScope.st1 }<br>
${st2 }
${requestScope.st2 }<br>
${st3 }
${sessionScope.st3 }<br>
${st4 }
${applicationScope.st4 }<br>
<%="st5=" %>
${st5 }<br>
如果变量名冲突:${st6 }<br>
</body>
</html>

如果不指定查找域,直接引用域中的属性名,EL会在page、request、session、application这4个作用域中按顺序依次查找属性。

param和paramValues对象

在JSP页面中,经常需要获取客户端传递的请求参数,为此,EL表达式提供了param和paramValues两个隐式对象专门用于获取客户端访问JSP页面时传递的请求参数。
1、param对象
param对象用于获取请求参数的某个值,它是Map类型,与request.getParameter()方法相同,在使用EL获取参数时,如果参数不存在,返回的是空字符串,而不是null。

${param.num}

2、paramValues对象
如果一个请求有多个值,可以使用paramValues对象来获取请求参数的所有值,该对象用于返回请求参数所有值组成的数组,如果要获取某个请求参数的第一个值

${paramValue.nums[0]}

1)param.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body style="text-align:center">
	<form action="${pageContext.request.contextPath}/param.jsp">
		num1:<input type="text" name="num1"><br>
		num2:<input type="text" name="num"><br>
		num3:<input type="text" name="num"><br>
		<input type="submit" value="提交"/><hr>
		num1:${param.num1 }<br>
		num2:${paramValues.num[0]}<br>
		num3:${paramValues.num[1]}<br>
	</form>
</body>
</html>

在这里插入图片描述

header和headerValues对象

当客户端访问Web服务器中的JSP页面时,会通过请求消息头传递一些信息,例如请求消息头中的“User-Agent”字段可以告诉服务器浏览器的类型。为了获取请求消息头中的信息,EL表达式提供了两个隐式对象header和headerValues。
1、header对象
用于获取请求头字段的某个值

${header["user-agent"]}

2、headerValues对象
该对象用于返回请求头字符的所有值组成的数组

${headerValues["Accept-Language"][0]}

Cookie对象

在JSP开发中,经常需要获取客户端的Cookie信息,为此在EL表达式中,提供了Cookie隐式对象,该对象是一个代表所有Cookie信息的Map集合,Map集合中元素的键为各个Cookie的名称,值则为对应的Cookie对象

获取cookie对象的信息:${cookie.userName}
获取cookie对象的名称:${cookie.userName.name}
获取cookie对象的值:${cookie.userName.value}

第一次访问没有cookie,第二次访问画面
在这里插入图片描述

initParam对象

在开发一个Web应用程序中,通常会在web.xml文件中配置一些初始化参数,为了便于获取这些参数,EL表达式提供了一个initParam隐式对象,该对象可以获取Web应用程序中全局初始化参数

${initParam.count}

1)在web.xml中的<web-app>元素下增加一个<context-param>子元素

  <context-param>
  	<param-name>webSite</param-name>
  	<param-value>www.baidu.com</param-value>
  </context-param>

2)initparam.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
初始化参数webSite的值为:<br>
${initParam.webSite }
</body>
</html>

在这里插入图片描述

自定义EL函数

EL表达式简化了JSP页面的书写,使不懂Java编程的开发人员也可以编写强大的JSP页面。但EL表达式本身功能有限,例如,对于循环语句,EL表达式就很难实现。因此,EL表达式运行用户自定义EL函数。

HTML注入

在JSP开发中,经常会提交一些包含"<"、">"等特殊HTML字符的数据,如果程序不对这些特殊字符进行转换,浏览器会把这些字符当作HTML标签进行解释执行,这就是所谓的HTML注入。

案例_自定义EL函数防止HTML注入

1)开发自定义EL函数,首先需要编写一个执行自定义函数功能的Java类,编写的Java类必须定义为public,并且作为函数的方法必须声明为public static类型。接下来编写一个Java类,用于实现HTML编码转换。
HTMLFilter.java

package EL;

public class HTMLFilter {
	public static String filter(String message){
		if(message==null){
			return(null);
		}
		char content[]=new char[message.length()];
		message.getChars(0, message.length(), content, 0);
		StringBuffer result=new StringBuffer(content.length+50);
		for(int i=0;i<content.length;i++){
			switch(content[i]){
				case '<':
					result.append("&lt;");
					break;
				case '>':
					result.append("&gt;");
					break;
				case '&':
					result.append("&amp;");
					break;
				case '"':
					result.append("&quot;");
					break;
				default:
					result.append(content[i]);
			}
		}
		return result.toString();
	}
}

2)为了让Java类的静态方法可以被EL表达式调用,需要在一个标签库描述符(tld)文件中对EL自定义函数进行描述,将Java类的静态方法映射成一个EL自定义函数,接下来编写一个描述自定义EL函数的mytagkib.tld文件,该文件放置到WEB-INF目录中或WEB-INF目录下的除了classes和lib目录之外的任意子目录中。
mytagkib.tld

<?xml version="1.0" encoding="UTF-8" ?>
 
<taglib xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
 
  <description>JSTL 1.1 core library</description>
  <display-name>JSTL core</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>c</short-name>
  <uri>http://myFunction.com</uri>
 <function>
 	<name>filter</name>
 	<function-class>
 		EL.HTMLFilter
 	</function-class>
 	<function-signature>
 		java.lang.String filter(java.lang.String)
 	</function-signature>
 </function>
 
</taglib>

3)result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="myFunction" uri="http://myFunction.com" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
	String message="<script type='text/javascript'>alert(1)</script>";
	pageContext.setAttribute("message", message);
%>
用户名:$(name)<br/>
留言信息:${myFunction:filter(message) }
</body>
</html>

在这里插入图片描述
可以看到原本的HTML内容被显示了出来,避免了HTML注入。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值