文章目录
- EL 表达式是干什么用的
- EL 表达式的底层原理
- EL 表达式可以用在哪些地方
- EL 表达式用来访问 JavaBean 的属性
- EL 表达式获取请求参数的值
- EL 表达式用于运算,将结果作为标签的属性值或者直接输出
- Struts2 的 EL 表达式
- EL 表达式翻译为 Java 代码的含义
- EL 表达式示例
- EL 表达式用在 xml 文件中
EL 表达式是干什么用的
EL 表达式的全称是 Expression Language,是一种表达式语言。 其语法格式:${el表达式}
。
EL 表达式可以直接使用,并不需要额外的配置或者引入什么文件。
EL 表达式依次从 pageContext、request、session、application 四个隐含对象中找到指定绑定名称对应的对象,然后获取对象的属性值直接输出到页面中,或者获取对象的属性值后再进行计算,将最后的结果输出到页面中。
EL 表达式经常用来给 JSTL 标签的属性赋值。
EL 表达式用字符串表达式替换 Java 代码,用来表示对数据的获取或计算。EL 表达式解决了 Java 代码和 HTML 的不匹配问题(让 HTML 页面中不再有 Java 代码)。
EL 表达式的底层原理
当 JSP 转换成对应的 Servlet 类时,会在 service 方法体内生成 EL 表达式对应的 Java 代码。这段 Java 代码就是依次调用 pageContext、request、session、application 对象的 getAttribute()
方法,然后将获取到的数据作为 out 对象的 print() 方法的实参,最终输出到页面中。
EL 表达式可以用在哪些地方
EL 表达式不可以在 JS 语境中使用,即不能在 </script>
标签体内使用。
EL 表达式不可以在 Java 语境中使用。
EL 表达式可以使用在 JSP、XML、HTML 等文件中,在这些文件中 el 表达式可以单独使用。
EL 表达式经常和 JSTL 标签结合使用,用在标签的属性值中,用来给标签属性赋值。
EL 表达式可以用在 HTML 标签的属性值中。
具体参见《EL 表达式教程》。
EL 表达式用来访问 JavaBean 的属性
示例:${user.name}
JSP 引擎会依次从 pageContext、request、session、application 查找绑订名为"user" 的对象,如果找到了,就不再向下查找;否则,继续向下查找。找到后,调用该对象的 getName()
,并输出其值;找不到,则输出"" (空)。
或者也可以使用 ${user["name"]}
, 效果相同 "name"
表示字符串。
或者是 ${user[propname]}
,注意 propname 没有引号,表示变量。
此外,[]
里面还可以是 0,1,2… 这样的下标,作用是输出数组里的元素值。
可以使用 pageScope,requestScope,sessionScope,applicationScope 四个关键字指定查找的范围。例如:${requestScope.user.name}
只到 request 中去找,不再依次到 4 个范围查找了。
示例代码:
<%--Created by IntelliJ IDEA.User: liaowenxiongDate: 2022/2/4Time: 15:42To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="priv.lwx.el.bean.*" %>
<html>
<%--访问bean的属性--%>
<head><title>Title</title>
</head>
<body style="font-size:30px;">
<%User user = new User();user.setName("liaowenxiong");user.setAge(22);IdCard card = new IdCard();card.setCardNo("100");user.setCard(card);user.setInterest(new String[]{"fishing", "sleep"});request.setAttribute("user1", user);
%>
<%--基本类型--%>
${user1.name}<br/>
${user1["name"]}<br/>
${user1.age}<br/>
<%--引用类型--%>
${user1.card.cardNo}<br/><%request.setAttribute("propname", "name");
%>
${user1[propname]};<br/>
<%--输出数组元素值--%>
${user1.interest[1]}
user's name:${requestScope.user1.name}
</body>
</html>
EL 表达式获取请求参数的值
${param.username}
等价于 request.getParameter("username");
${paramValues.interest}
等价于 request.getParameterValues("interest");
<%--Created by IntelliJ IDEA.User: liaowenxiongDate: 2022/2/4Time: 16:14To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<%--获取请求参数值--%>
<head><title>Title</title>
</head>
<body style="font-size:30px;">
username:${param.username}<br/>
interest:${paramValues.interest[0]}
interest:${paramValues.interest[1]}
interest:${paramValues.interest}
</body>
</html>
EL 表达式用于运算,将结果作为标签的属性值或者直接输出
<%--Created by IntelliJ IDEA.User: liaowenxiongDate: 2022/2/4Time: 16:29To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.*" %>
<%@ page import="javax.servlet.jsp.*" %>
<html>
<head><title>Title</title>
</head>
<body style="font-size:30px;">
<%--算术运算--%>
${1+2}<br/>
${"245"+"456"}<br/>
<hr>
<%--关系运算--%>
${"abc" == "abc"}
${"abc" eq "abc"}
<hr>
<%pageContext.setAttribute("str", "abc");
%>
<%--el表达式会从pageContex对象中获取到属性str的值,然后再和字符串"abc"比较,最后将比较结果输出到页面中--%>
${"abc" eq str}<br/>
<%--empty运算--%>
<%request.setAttribute("str1", "");List list = new ArrayList();request.setAttribute("list1", list);request.setAttribute("obj1", null);
%>
<%--空字符串的结果为true--%>
${empty str1}<br>
<%--找不到指定绑定名对应的对象,结果为true--%>
${empty obj}<br>
<%--集合内容为空,结果为true--%>
${empty list1}<br>
<%--null,结果为true--%>
${empty obj1}<br>
</body>
</html>
Struts2 的 EL 表达式
Struts2 的 V 层组件一般是 JSP 文件,在 JSP 文件中可以通过 el 表达式、ognl 表达式、jstl 标签库、struts2 提供的标签来获取 Action 组件中的属性值。
使用 el 表达式不需要引入额外的 jar 包;要使用 ognl 表达式,要引入 ognl-2.7.3.jar
包;要使用 jstl
标签,要引入 jstl.jar
和 standard.jar
包并且在 JSP 文件中要使用指令引入 jstl 标签库。在 Struts2 项目中使用 Struts2 的标签不要引入额外的 jar 包,但是 JSP 文件中需要使用指令引入 Struts2 的标签库。
其实 struts.xml 中配置的 V 层组件,默认情况下控制器是通过转发的机制去调用的,按道理说控制器可以将 Action 组件的属性值先绑定到 request 对象中,再转发给某个 jsp 文件,那么 jsp 中的 el 表达式就可以从 request 对象中找到数据了。实际情况并非如此的。
在 Struts2 的项目中,JSP 文件中获取到 request 对象并不是服务器生成的,而是 Struts2 提供的包装类 StrutsRequestWrapper 的对象,这个包装类实际上是 HttpServletRequest 的衍生类,StrutsRequestWrapper 类重写了 getAttribute() 方法,这个方法会先去访问服务器生成的 request 对象,如果获取不到指定属性的值再去访问 ValueStack 对象中的属性 root 和 context。
所以在 Struts2 项目中,el 表达式表面还是去访问 pageContext、request、session、application 四个对象获取指定属性的值。只不过在访问 request 对象时,底层是先去访问服务器生成的原始 request 对象,获取不到再去访问 ValueStack 对象的属性 root 和 context。
如果按标准 el 表达式访问的域对象来排序,Struts2 中的 el 表达式访问域对象的实际顺序是:
pageContext、request、ValueStack、session、application
所以在 Struts2 项目中,el 表达式如果无法从 pageContext、request 对象获取到数据,那么就会执行以下的代码去访问 ValueStack:
Object obj = Ognl.getValue("OGNL表达式",root,context);
el 表达式 ${author}
,可以获取到 Action 对象的 author 属性值,其实是调用该 Action 对象 getAuthor()
方法,如果 Action 类中没有定义变量 author,却有 getAuthor()
方法,${author}
最后也会调用 Action 对象的 getAuthor()
方法。
总结:Struts2 的 el 表达式底层有去调用 Ognl 引擎,访问 ValueStack 的属性 root 和 context,而且访问 context 获取指定属性的值并无需在属性名前加 #
。
EL 表达式翻译为 Java 代码的含义
举例说明下:
${foo.name}
翻译为 Java 代码是 out.print(foo.getName());
,意味着调用对象 foo
的 getName()
方法,而非直接访问对象 foo
的实例变量 name
,同时注意实例变量一般是私有的,不能直接访问。
另外,JSP 引擎会依次从 pageContext、request、session、application 查找绑订名为“foo”的对象。
注:其实 out.write()
、out.print()
都是先把 html 文本数据输出到 response 对象中,然后 web 服务器再把 response 对象中的数据响应个浏览器端进行加载和解析,最后显示出来给用户看。
EL 表达式示例
EL 表达式:${empty str1}
JSP 引擎会依次从 pageContext、request、session、application 查找绑订名为“str1”的对象,如果找到了就不再向下查找,否则继续向下查找。找到后判断值是否为空,如果是空字符串,则返回 true,如果是个空集合,也返回 true,如果找不到绑定名为“str1”的对象,也返回 true,如果是 null,也返回 true。再将 true
这个值输出到页面中,最后响应给浏览器显示出来。
EL 表达式:${user.name}
或 ${user["name"]}
JSP 引擎会依次从 pageContext、request、session、application 查找绑订名为"user" 的对象,如果找到了,就不再向下查找;否则,继续向下查找。找到后,调用该对象的 getName()
,并输出其值;找不到,则输出"" (空)。
EL 表达式:${requestScope.user.name}
表示只到 request 中查找,不再依次从 pageContext、request、session、application 查找。
EL 表达式用在 xml 文件中
在 Struts2 项目中,我们在 struts.xml 文件中可以使用 EL 表达式获取属性值,如下所示:
<action name="user" class="priv.lwx.struts2.UserAction"> <result name="success" type="dispatcher">/WEB-INF/jsp/user.jsp?userId=${user.userId}</result>
</action>