文章目录▼CloseOpen
- EL表达式到底是什么?用大白话给你讲清楚
- EL表达式怎么用?分场景教你实操
- 场景1:快速取出作用域里的数据
- 场景2:轻松处理表单提交的参数
- 场景3:用简单运算符做逻辑判断
- 场景4:用内置对象简化开发
- EL表达式的常见坑,我踩过的你就别踩了
- 坑1:用EL做复杂逻辑
- 坑2:忘记处理嵌套对象的空值
- 坑3:混淆EL和Java的语法
- 坑4:用EL输出敏感数据
- EL表达式到底能帮我解决什么问题?
- EL表达式为什么能直接写${user.name},不用强转对象?
- 用EL表达式取嵌套对象(比如${user.address.city})时,怎么避免报错?
- EL表达式能做循环或者复杂逻辑吗?比如遍历一个用户列表?
- EL输出的内容会自动转义特殊字符吗?比如用户输入的标签?
- 所有EL表达式都用
${}
包裹,没例外; - 里面可以写变量(比如
${user}
)、属性(比如${user.name}
)、运算符(比如${a + b}
)、内置对象(比如${param.username}
); - 变量不用声明,EL会自动从四个作用域(pageScope→requestScope→sessionScope→applicationScope)里找,找不到就返回空字符串(不是null,这点特别友好)。
- 取请求作用域里的用户对象:
${requestScope.user}
(明确指定作用域,避免同名变量冲突); - 取用户对象的姓名:
${user.name}
(EL会自动找user
对象的getName()
方法); - 取会话作用域里的购物车:
${sessionScope.cart}
; - 取应用作用域里的系统名称:
${applicationScope.systemName}
。 - 取表单里的用户名:
${param.username}
; - 取表单里的密码:
${param.password}
; - 取复选框的多个值(比如爱好):
${paramValues.hobby[0]}
(paramValues
存多个值的参数,返回数组)。 - 判断用户年龄是否大于18:
${user.age > 18}
(返回true或false); - 判断用户是否登录:
${empty user}
(如果user
不存在或为空,返回true); - 显示登录状态:
${empty user ? '请登录' '欢迎你,${user.name}'}
(三元运算符,一句话搞定); - 计算商品总价:
${product.price product.quantity}
(算术运算符,直接算总价)。
EL表达式到底是什么?用大白话给你讲清楚
EL表达式其实就是JSP给我们的“偷懒工具”——专门用来替代页面里的Java脚本,帮你快速取出作用域里的数据,或者做简单的逻辑判断。它的样子很好认,就是用${}
把内容包起来,比如${user.name}
,意思就是“从作用域里找叫user
的对象,然后取出它的name
属性”——是不是比简单一百倍?我当初第一次用的时候,盯着这个表达式看了三秒,拍着大腿说“这也太香了吧!”
那EL到底能帮我们做什么? 下来就两件事:取数据和做简单逻辑。取数据是它最擅长的——不管是作用域里的对象(比如request里的user
)、表单提交的参数(比如username
),还是Cookie里的值,它都能快速拿出来;做简单逻辑就是帮你判断个“有没有”“大不大”,比如${user.age > 18}
“${empty cart}”,不用写if-else脚本。
我当初学EL的时候,最担心“语法记不住”,后来发现根本不用死记——它的语法规则比小学乘法表还简单:
举个例子:你在Servlet里用request.setAttribute("user", new User("张三", 25))
把用户对象放到请求作用域,那JSP页面里要显示用户名,直接写${user.name}
就行——EL会自动帮你做三件事:①从作用域里找到user
对象;②调用user.getName()
方法;③把结果输出到页面。你看,是不是比写Java脚本省了至少三行代码?
EL表达式怎么用?分场景教你实操
我当初学EL的时候,最头疼的是“不知道什么时候用”,后来把常用的场景列了个清单,现在跟着我一个个过,你马上就会用——而且这些场景覆盖了开发中80%的需求。
场景1:快速取出作用域里的数据
这是EL最常用的功能,没有之一。不管是request、session还是application里的对象,EL都能帮你“一键提取”。比如:
我帮小周改代码的时候,他问:“如果我不写requestScope
,直接写${user}
,EL会从哪找?”其实EL有个“默认搜索顺序”——pageScope→requestScope→sessionScope→applicationScope,也就是先找页面作用域,找不到再找请求,依此类推。但我 你尽量明确指定作用域,比如${requestScope.user}
,因为如果有同名变量(比如页面作用域里也有个user
),EL会先取页面里的,结果可能不是你想要的——我之前就踩过这个坑:session里有个user
,页面里又用pageContext.setAttribute("user", null)
,结果${user}
显示空,我还以为EL坏了,后来加了sessionScope
就好了。
场景2:轻松处理表单提交的参数
有时候你需要取表单里的参数,比如用户输入的用户名、密码,用EL的话比request.getParameter()
方便一百倍——因为EL的param
内置对象专门存请求参数,而且不用处理null的情况(参数不存在时返回空字符串)。比如:
我做登录页面的时候,用${param.username}
把用户输入的用户名回显到输入框里,代码是这样的:——比用
request.getParameter("username")
省了至少两行代码,而且不会像Java那样抛空指针(如果用户没输入,${param.username}
返回空字符串,输入框还是空的,很友好)。
场景3:用简单运算符做逻辑判断
EL支持算术运算符(+、-、、/)、比较运算符(>、<、==)、逻辑运算符(&&、||、!),还有空运算符(empty)——这些运算符足够应付页面里的简单逻辑,不用写if-else脚本。比如:
我经常用empty
运算符判断数据是否存在,比如用户详情页里的地址:${not empty user.address ? user.address.city '未填写'}
——如果user.address
是null,就显示“未填写”,否则显示城市名。我之前没加这个判断,结果页面直接报错(因为user.address
是null,调用user.address.city
会抛异常),后来加了empty
就好了——这个坑你可别踩。
场景4:用内置对象简化开发
EL有11个内置对象,其中最常用的就是param
、paramValues
、requestScope
、sessionScope
、applicationScope
——我把这些常用的内置对象整理成了表格,你可以直接存下来当 cheatsheet:
内置对象名 | 作用 | 示例 |
---|---|---|
requestScope | 存储请求作用域中的数据 | ${requestScope.user} |
sessionScope | 存储会话作用域中的数据 | ${sessionScope.cart} |
applicationScope | 存储应用作用域中的数据 | ${applicationScope.systemName} |
param | 存储单个请求参数(比如输入框) | ${param.username} |
paramValues | 存储多个请求参数(比如复选框) | ${paramValues.hobby[0]} |
比如paramValues
,我做兴趣调查页面的时候用过:用户选了“读书”“运动”两个爱好,表单里的name
是hobby
,用${paramValues.hobby}
就能拿到一个字符串数组,要取第一个爱好就是${paramValues.hobby[0]}
——比用request.getParameterValues("hobby")
简单太多了。
EL表达式的常见坑,我踩过的你就别踩了
EL虽然好用,但新手容易犯一些低级错误——我把自己踩过的坑整理了,你看完就能避开:
坑1:用EL做复杂逻辑
EL只能做简单逻辑(比如判断、算术运算),复杂的逻辑(比如循环、嵌套判断)还是要用到JSTL标签(比如
)。我当初想让EL帮我循环遍历一个列表,写了
${for (item in list)}
,结果页面直接报错——后来才知道EL不支持循环,得用JSTL的配合:
,然后里面写
${u.name}
——这个组合才是“黄金搭档”。
坑2:忘记处理嵌套对象的空值
比如${user.address.city}
,如果user.address
是null,EL会抛PropertyNotFoundException(属性未找到异常)——因为address
是null,没法调用getCity()
方法。解决办法是用empty
先判断:${not empty user.address ? user.address.city '未填写'}
——我做用户详情页的时候没加这个判断,结果页面报错,后来加了就好了。
坑3:混淆EL和Java的语法
EL的语法和Java有点像,但不完全一样——比如EL里的相等判断是==
,但Java里是equals()
;EL里的逻辑与是&&
,和Java一样,但EL里的空判断是empty
,Java里是null
。我之前写${user.name == '张三'}
,结果没匹配上,后来才知道user.name
是"张三 "
(后面有个空格),所以要注意字符串的trim——或者用JSTL的标签配合
trim="true"
。
坑4:用EL输出敏感数据
EL会自动把特殊字符转义吗?比如${user.name}
如果是,EL会输出
吗?不会——EL默认不转义特殊字符,所以如果输出用户输入的内容(比如评论),要配合JSTL的
标签,比如
——否则会有XSS攻击的风险。我之前做评论功能的时候没转义,结果有人输入
alert('XSS')
,页面直接弹出alert——后来加了就好了。
其实EL表达式真的是JSP里最友好的工具之一,你今天跟着我学的这些,足够应付80%的开发场景了——而且用完你会发现,JSP页面里的Java脚本少了,维护起来方便多了。我帮小周改完代码后,他跟我说:“现在写页面再也不用翻Java语法书了,EL比我想象的简单一百倍!”
如果你按我说的试了,比如把页面里的Java脚本换成EL,欢迎回来告诉我你的页面清爽了多少!还有什么不懂的,评论区问我,我帮你解答—— 踩过坑的人最懂怎么避坑~
EL表达式到底能帮我解决什么问题?
EL其实就是JSP给你的“偷懒神器”,专门帮你替代页面里冗余的Java脚本。比如你之前要取request里的用户姓名,得写这么长一串,现在用${user.name}就行;要取表单里的用户名,不用request.getParameter(“username”),直接写${param.username};甚至想判断用户年龄是不是大于18,也不用写if脚本,用${user.age > 18}就搞定。 下来,它主要帮你做两件事:快速取出作用域、表单里的数据,以及做简单的逻辑判断,让你的JSP页面清爽很多。
EL表达式为什么能直接写${user.name},不用强转对象?
这是EL最贴心的设计——它会自动帮你做“找对象+强转+调用方法”三件事。比如${user.name},EL会先从page、request、session、application这四个作用域里按顺序找叫“user”的对象;找到后,自动帮你强转成对应的类型(比如User类);最后调用这个对象的getName()方法,把结果输出。所以你不用像写Java脚本那样,手动强转或者调用get方法,直接写属性名就行,省了好多麻烦。
用EL表达式取嵌套对象(比如${user.address.city})时,怎么避免报错?
新手最容易踩的坑就是这个——如果user的address属性是null,直接写${user.address.city}会报错(因为null没法调用getCity())。解决办法很简单:先用empty判断嵌套对象有没有值。比如改成${not empty user.address ? user.address.city ‘未填写’},意思是“如果user.address不是空,就取city;否则显示未填写”。我之前做用户详情页的时候没加这个判断,页面直接报错,后来加了就好了,你可别犯同样的错。
EL表达式能做循环或者复杂逻辑吗?比如遍历一个用户列表?
EL只能处理简单逻辑(比如判断、算术运算),复杂的循环或者嵌套判断得配合JSTL标签用。比如你想遍历用户列表,单靠EL不行,得用JSTL的标签:先写,然后在里面用${u.name}显示每个用户的姓名。EL和JSTL是“黄金搭档”,EL负责取数据,JSTL负责复杂逻辑,这样组合起来才好用。
EL输出的内容会自动转义特殊字符吗?比如用户输入的标签?
注意啦,EL默认不会转义特殊字符!比如用户输入了alert(‘XSS’),直接用${user.comment}输出的话,页面会弹出alert框,有安全风险。要解决这个问题,得配合JSTL的标签,写成,这样特殊字符会被转成这种形式,就不会执行了。我之前做评论功能的时候没转义,结果被人搞了XSS攻击,后来加了就好了。