El表达式详解

这是我的第一篇技术blog,我写技术blog一是为了能把知识写成电子版的笔记积累下来,整理的同时记忆也就更加深刻,二来也能分享给其ta人,让需要他们的码农们从中收益。为什么要从EL开始写呢,我辞去上一份工作的一部分原因就是servlet和mobile page数据交互出了一些问题搞不定,所以我这次想把这部分知识好好总结一下,全当再次学习一遍了。


EL简介

EL表达式(Expression Language)由两个开发团队共同开发,JSP 标准标签库专家组和JSP 2.0 专家组,这就说明了EL表达式在JSP2.0以后的版本才被支持。根据个人理解,EL表达式的主要作用就是简化JSP的开发,避免页面出现大量的JSP代码使美工的工作更加困难。EL表达式的使用情形大致有以下两种:在JSP页面中输出静态内容 、为JSTL和自定义标签提供属性值。EL表达式的语法格式为${ }

EL表达式的作用

  • 在JSP页面执行运算(关系、逻辑、算术)
  • 访问作用域中的对象
  • 访问JSP隐式对象中的属性
  • 访问客户端请求中的参数信息
  • 访问JavaBean的属性
  • 访问集合元素
下面结合实际的代码对上述EL表达式的作用予以一一说明。

通过EL表达式在JSP执行运算(算术、逻辑、关系)
[plain]  view plain  copy
 
  1.   
  2. 2*3=${2*3}  
  3. 100>150=${100>150}  
  4. true&&false=${true&&false}  
  5.   
运行之后即会显示:
[plain]  view plain  copy
 
  1. 2*3=6  
  2. 100>150=false  
  3. true&&false=false  
个人认为这种运算确实没有什么实际意义,只要明白EL表达式有这种运算能力即可,说到这里要提一下如何禁用EL表达式了,具体分为以下两种:
  • 全局禁用:设置JSP的page属性isELIgnored="false",这样即可禁用本页面所有的EL表达式。
  • 局部禁用:在EL表达式的$符号前加一个反斜杠\,例如:
[plain]  view plain  copy
 
  1. 2*3=\${2*3}  
  2. 100>150=\${100>150}  
  3. true&&false=\${true&&false}  
运行之后即会显示:
[plain]  view plain  copy
 
  1. 2*3=${2*3}  
  2. 100>150=${100>150}  
  3. true&&false=${true&&false}  

通过EL表达式访问作用域中的对象

个人认为这是EL表达式最常用以及最主要的作用,例如:

[plain]  view plain  copy
 
  1. <%request.setAttribute("age", 10);%>  
  2.   
  3. ${age}  
  4.   
运行之后即会显示:
[plain]  view plain  copy
 
  1. 10  
这里有必要列举一下特殊情况,当多个name相同的对象被放到不同的作用域,EL表达式会按照什么顺序显示读取呢?例如:
[plain]  view plain  copy
 
  1. <%  
  2. request.setAttribute("user", "user--request");  
  3. session.setAttribute("user", "user--session");  
  4. pageContext.setAttribute("user", "user--pageContext");  
  5. application.setAttribute("user", "user--application");  
  6. %>  
[plain]  view plain  copy
 
  1.   
  2. ${user}  
  3.   
上述4个对象name相同,被放到了不同的作用域,通过EL表达式读取,运行后即会输出:
[plain]  view plain  copy
 
  1. user--pageContext  
通过上述测试不难发现:EL表达式访问作用域对象时若同时存在多个同名对象,默认情况下会有先后顺序。具体顺序如下:
pageContext--->request--->session--->application
当然上述的顺序只是同名情况下的默认情况, 如果即使同名我也想获取我所指定作用域中的对象,则需要使用EL表达式的隐式对象了。
同样以上述情况为例,如果我想取session作用域中的对象,那么即可这样写:
[plain]  view plain  copy
 
  1.   
  2. ${sessionScope.user}  
  3.   

运行之后即会显示:

[plain]  view plain  copy
 
  1. user--session  

这就说明了: 我们可以根据需要去改变同名下的默认获取顺序来得到我们想要的数据
既然提到了sessionScope,那有人就会问有没有requestScope?applicationScope?这些则必然会有,他们都属于 EL的隐式对象,下面就总结一下都有哪些隐式对象:
  • pageContext(pageScope、sessionScope、requestScope、applicationScope) 提供对页面属性的访问
  • param 返回客户端请求参数的参数值
  • paramValues 返回客户端请求参数的一组值
  • header 返回请求的标题名称
  • headerValues 返回请求标题的一组值
  • cookie 返回cookie对象的对象名称
  • initParam 返回上下文初始化参数的名称
上述隐式对象常用的主要就是前三个,在此就不一一举例,有兴趣的朋友不妨自己试一试,如法炮制。

通过EL表达式获取参数值

通过EL的隐式对象可以获取客户端传递的参数的值,例如:

当客户端访问http://localhost:8080/el_test/test01.jsp时传递一个参数:http://localhost:8080/el_test/test01.jsp?u1=abc

那么在该jsp页面就可以通过EL表达式获取u1的参数值,写法如下:

[plain]  view plain  copy
 
  1. ${param.u1}  
运行之后即会显示:

[plain]  view plain  copy
 
  1. abc  
这里有可能出现一种特殊情况,就是参数名带点,例如如果参数名是u1.u1,那么用EL表达式获取参数值就会出现下面的情况:

[plain]  view plain  copy
 
  1. ${param.u1.u1}  
这样显示是不妥的,会混淆。那么我们有一种更好的选择,EL表达式对此种情况也支持下面的写法:

[plain]  view plain  copy
 
  1. ${param['u1.u1']}  

[plain]  view plain  copy
 
  1. ${param["u1.u1"]}  

通过上述的写法就很好的避免了容易混淆的情况,因为不管参数名是什么格式,都会被包在引号之间。

以上只是单参数的情况,那么也有可能是同名的多参数,经常会有这种需求:兴趣爱好会有多个,但参数名都相同,那么EL怎么处理呢?同样是隐式对象,例如:http://localhost:8080/el_test/test01.jsp?hobby=1&hobby=2&hobby=4

那么如果通过EL表达式获取多个参数值的话必须接受的是一个数组,那么就要用到了paramValues这个隐式对象,例如:

[plain]  view plain  copy
 
  1. ${paramValues.hobby[0]}  
这样就能得到了hobby数组的第0号元素,取法和普通的数组一样,下标都是从0开始,运行后即会显示:
[plain]  view plain  copy
 
  1. 1  
paramValues.hobby也就等同于request.getParamterValues(),毕竟EL背后的实现也都是java代码。


通过EL表达式访问作用域中的JavaBean

其实原理和上述的“访问作用域中的对象”都是一样的,所以这里就不再详细赘述,举个例子便一目了然。

首先定义一个JavaBean:

[java]  view plain  copy
 
  1. public class User{  
  2.   
  3.    private String userId;  
  4.    private String userPwd;  
  5.      
  6.    public String getUserId(){  
  7.        return userId;  
  8.    }  
  9.   
  10.    public void setUserId(String userId){    
  11.        this.userId=userId;  
  12.    }  
  13.   
  14.    public String getUserPwd(){  
  15.        return userPwd;  
  16.    }  
  17.   
  18.    public void setUserPwd(String userPwd){  
  19.        this.userPwd=userPwd;  
  20.    }  
  21.   
  22.     public User(String userId,String userPwd){  
  23.        this.userId=userId;  
  24.        this.userPwd=userPwd;  
  25.    }  
  26.   
  27. }  
将对象放进作用域:

[plain]  view plain  copy
 
  1. <%  
  2. User user=new User("u1","123");  
  3. request.setAttribute("user",user);  
  4. %>  
读取对象的属性:

[plain]  view plain  copy
 
  1. ${user.userId}  
运行后即会显示:

[plain]  view plain  copy
 
  1. u1  
这里需要强调一点就是EL表达式是如何获取JavaBean的属性,我们做一个实验,在上述的User类里面加入下面这段代码:

[java]  view plain  copy
 
  1. public String getBeanXxx(){  
  2.     return "xxx";  
  3. }  
然后依然通过EL读取这个属性:

[plain]  view plain  copy
 
  1. ${user.beanXxx}  
运行后即会显示:
[plain]  view plain  copy
 
  1. xxx  
为什么连beanXxx这个字段都没有定义,只是加了一个get方法,就能得到值了呢?没错,这就是EL获取对象属性的原理:

EL表达式会根据字段去类里面寻找这个字段的get方法,即自动给该字段首字母变大写并加上get前缀,一旦找到有完全匹配的方法,那EL表达式就会认为这就是我们要得到的对象属性,即便实际上他并不是该对象的属性。所以说,如果想通过EL获取对象属性,那么必须有标准的get方法

通过EL表达式访问作用域中的数组和List/Map集合

通过介绍了这么多,我们自己或多或少都能总结出了一些规律了吧!不管是哪种数据类型,方法和规则基本都是类似的,下面举例说明。首先给作用域中放一个int类型数组:

[plain]  view plain  copy
 
  1. <%request.setAttribute("arr",new int[]{1,3,5,6,8});%>  
获取第一个数组元素:

[plain]  view plain  copy
 
  1. ${arr[0]}  
运行后即会显示:
[plain]  view plain  copy
 
  1. 1  
很简单吧!同样的道理,访问Map集合也差不多。

首选给作用域中放一个Map类型的对象:

[plain]  view plain  copy
 
  1. <%  
  2.     Map map=new HashMap();  
  3.     map.put("o1",123);  
  4.     map.put("o2",223);  
  5.     map.put("o3",323);  
  6.     request.setAttribute("map",map);  
  7. %>  
根据key值获取value:

[plain]  view plain  copy
 
  1. ${map.o1}  

[plain]  view plain  copy
 
  1. ${map['o1']}  

[plain]  view plain  copy
 
  1. ${map["o1"]}  
运行后即会显示:
[plain]  view plain  copy
 
  1. 123  

最后还需要提及一点就是EL对于获取不到的值默认是置空处理(置为空串),这就很符合我们用户的良好体验,避免异常或者null符号混淆用户。


好了,到这里大体上就对EL表达式的基本的常见的用法介绍的差不多了,上面的所有源代码均经过本人成功测试,大可不必怀疑。不放心的朋友可以自己再核实一下,多练一遍记忆便会更深了!本人的第一篇技术blog暂时写到这里,欢迎各位读者朋友批评指正,共同学习交流,毕竟我也是个初出茅庐java菜鸟。当然以后依然会对此继续补充、完善,就像我的blog简介一样, 我是处女座,我追求完美 ,大到技术问题小到字体样式我都力争做到完美,要么不做,要么做到最好,这就是我一贯的宗旨,我以后的技术blog依旧会坚持这一原则。提前感谢大家的鼓励和支持。谢谢!

你可能感兴趣的:(javaee,El表达式详解)