> 文档中心 > EL表达式 | 深入学习EL表达式

EL表达式 | 深入学习EL表达式

目录

一:深入学习EL表达式

1、什么是EL表达式

2、EL表达式的主要作用

3、EL表达式的使用

4、面试题 :${abc} 和 ${"abc"}的区别

5、EL表达式读取数据的顺序

6、EL表达式对null进行了预处理

7、EL表达式取数据的时候有两种形式

8、从Map集合中取数据

9、从数组和List集合中取数据

10、设置忽略EL表达式

11、通过EL表达式获取应用的根

12、常用的隐式对象

13、EL表达式的运算符


一:深入学习EL表达式

1、什么是EL表达式

①EL表达式:Expression Language(表达式语言) 。

EL表达式可以代替JSP中的java代码,让JSP文件中的程序看起来更加整洁,美观。

③JSP中夹杂着各种java代码,例如、等,导致JSP文件很混乱,不好看,不好维护!所以才有了后期的EL表达式。

EL表达式可以算是JSP语法的一部分,EL表达式归属于JSP

2、EL表达式的主要作用

从某个作用域中取数据,然后将其转换成字符串,然后将其输出到浏览器。这就是EL表达式的功效;三大功效:

第一功效:从某个域中取数据。 四个域:pageContext、request、session、application

第二功效:将取出的数据转成字符串。如果是一个java对象,也会自动调用java对象的toString方法将其转换成字符串。

第三功效:将字符串输出到浏览器。和效果一样,将其输出到浏览器。

3、EL表达式的使用

${表达式}

①注意:EL表达式只负责取,不负责存。

②我们来看下面一个例子,调用 request的setAttribute("username","zhangsan");方法存入数据;以前取的话是使用这种方式取;但是现在使用EL表达式只需要简介的一句话:${username}。

${username}

①创建一个完整的javabean对象

package com.bjpowernode.javaweb.jsp;import java.util.Objects;/** *  * @Author:朗朗乾坤 * @Package:com.bjpowernode.oa.bean * @Project:JavaWeb * @name:Dept * @Date:2022/11/28 10:59 */public class Dept {    private String deptno;    private String dname;    private String loc;    // 构造方法    public Dept() {    }    public Dept(String deptno, String dname, String loc) { this.deptno = deptno; this.dname = dname; this.loc = loc;    }    // setter and getter    public String getDeptno() { return deptno;    }    public void setDeptno(String deptno) { this.deptno = deptno;    }    public String getDname() { return dname;    }    public void setDname(String dname) { this.dname = dname;    }    public String getLoc() { return loc;    }    public void setLoc(String loc) { this.loc = loc;    }    // 重写toString方法    @Override    public String toString() { return "Dept{" +  "deptno='" + deptno + '\'' +  ", dname='" + dname + '\'' +  ", loc='" + loc + '\'' +  '}';    }    // 重写equals方法 和 hashCode方法    @Override    public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Dept dept = (Dept) o; return Objects.equals(deptno, dept.deptno) &&  Objects.equals(dname, dept.dname) &&  Objects.equals(loc, dept.loc);    }    @Override    public int hashCode() { return Objects.hash(deptno, dname, loc);    }}

②把这个java对象放入到request域当中,并使用EL表达式取出

😊如果没有重写toString方法:com.bjpowernode.javaweb.jsp.Dept@38039c48

😊如果重写了toString方法:Dept{deptno='10', dname='研发部', loc='北京'}

${userObj}

那如果想取每个特定的属性呢?

😊不需要调用Dept类的对应get方法去获取得;而是直接调用属性名(暂时这样理解);实际上直接调用属性名,底层自己会调用对应的get方法!

😊${userObj} 底层是怎么做的?从域中取数据,取出user对象,然后调用user对象的toString方法,转换成字符串,输出到浏览器。

${userObj.deptno}  10 ${userObj.dname}   研发部 ${userObj.loc}     北京

😊注:实际上和属性名并没有太大的关系,只和get方法有关,例如:getDeptno()是把get和()都去掉,Deptno换成全小写的deptno,下面通过一个例子进行验证:

// 在Dept类中新增加一个getEmail()方法,但是没有声明email属性 public String getEmail() { return "123.com"; }// 使用.email也是能访问到的${userObj.email} // 123.com

😊所以如果想输出对象的属性值:

{userObj.deptno} 使用这个语法的前提是:User对象有getDeptno()方法。
${userObj.dname} 使用这个语法的前提是:User对象有getDname()方法。
${userObj.loc} 使用这个语法的前提是:User对象有geLoc()方法。
${userObj.email} 使用这个语法的前提是:User对象有getEmail()方法。
😊EL表达式中的. 这个语法,实际上调用了底层的getXxx()方法。

😊所以可以通过EL表达式${userObj.addr.zipcode}猜测对应的java代码
dept.getAddr().getZipcode()

😊注意:如果没有对应的get方法,则出现异常。报500错误。

4、面试题 :${abc} 和 ${"abc"}的区别

①${abc}表示从某个域中取出数据,并且被取的这个数据的name是"abc",之前一定有这样的代码: 域.setAttribute("abc", 对象);
②${"abc"} 表示直接将"abc"当做普通字符串输出到浏览器,不会从某个域中取数据了。

5、EL表达式读取数据的顺序

①EL表达式优先从小范围中读取数据。

②pageContext < request < session < application

<%--pageContext < request < session ${data}

③在EL表达式中可以指定范围来读取数据;EL表达式有4个隐含的隐式的范围对象:

😊pageScope 对应的是 pageContext范围。

😊requestScope 对应的是 request范围。

😊sessionScope 对应的是 session范围。

😊applicationScope 对应的是 application范围。

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

6、EL表达式对null进行了预处理

①EL表达式主要任务是做页面展示,要求最终页面展示上是友好的。

②所以EL表达式对null进行了处理。如果是null,则在浏览器上显示空白。

③EL表达式表面上是这种写法,实际上运行的时候,还是要翻译生成java代码的。

④${usernam} 这个EL表达式等同于三目运算符这一段java代码:

采用EL表达式:${username}采用EL表达式:${usernam}

7、EL表达式取数据的时候有两种形式

①前面我们已经学习了"."的形式取出数据

例如:${dept.dname}就等于${dept["dname"]},注意以"[]"形式取,一定要加上双引号[""]

②对于存在特殊字符的变量名,只能使用[""]的方式取

${requestScope.abc.def} 这样是无法取值的${requestScope["abc.def"]} 可以正常取值

8、从Map集合中取数据

语法格式:${map.key}

①创建一个Map集合,直接放入对应的数据后,在把Map集合放入request域

<%     // 创建一个Map集合    Map map = new HashMap();    // 存入数据到map集合    map.put("username", "zhangsan");    map.put("password", "123");    // 将Map集合存储到request域当中。    request.setAttribute("userMap", map);%>${userMap.username}${userMap["username"]}

②先创建一个Map集合;在创建一个User类,给对应的属性赋值后把User类放入Map集合,最后在把Map集合放入request域,怎么取数据?

    // 创建map集合    Map userMap = new HashMap();    // 创建user类    User user = new User();    // 给user类的name属性设置值    user.setUsername("lisi");    // 把user类放入map集合    userMap.put("user", user);    // 将Map集合存储到request域当中    request.setAttribute("map", userMap);%>${map.user.username}

9、从数组和List集合中取数据

①对于数组和List集合中取数据,都可以采用下标的形式进行取:

对于数组:${数组[0]}

${nameArray} ${nameArray[0]} ${nameArray[1]}${nameArray[2]}

对于list集合:${list[0]}

<%    //创建一个list集合    List list = new ArrayList();    // 调用add方法,添加数据    list.add("abc");    list.add("def");    // 把list集合放入request域    request.setAttribute("myList", list);%>${myList}${myList[0]}${myList[1]}

10、设置忽略EL表达式

①page指令当中,有一个isELIgnored属性,可以忽略EL表达式;

②默认是不忽略了,如果设置忽略,写出的EL表达式会被当做普通字符串输出 

③isELIgnored="true" 表示忽略JSP中整个页面的所有EL表达式。如果想忽略其中某个,可以使用反斜杠"\"!

isELIgnored="true" 表示忽略EL表达式isELIgnored="false" 表示不忽略EL表达式。(这是默认值)isELIgnored="true" 这个是全局的控制。可以使用反斜杠进行局部控制:\${username} 。

11、通过EL表达式获取应用的根

①我们已经知道JSP有九大内置对象:pageContext,request,session,application,response,out,config,page,exception;其中四个域对象,其中最小的域是pageContext(页面上下文),通过pageContext可以获取应用的根

②在内置对象pageContext中有一个getRequest()方法,可以用来获取到request对象;但是JSP中九大内置对象中已经包含了request对象;所以看起来这个方法没有什么用!

③实际上在EL表达式当中没有request这个隐式对象,前面讲的requestScope 这个只代表“请求范围”,不等同于request对象;但是在EL表达式当中有一个隐式的对象:pageContext, EL表达式中的pageContext和JSP中的九大内置对象pageContext是同一个对象;这就很有意思了;所以在EL表达式中虽然没有request隐式对象,但是可以通过隐式对象pageContex获取到request对象;就可以写出下面等价的代码:

// 在JSP中pageContext内置对象调用getRequest()方法获取到request对象// 对应到EL表达式中pageContext隐式对象的代码就是${pageContext.request}

④所以获取到应用的根,就可以通过EL表达式获取:${pageContext.request.contextPath}

// 直接通过request对象获取应用的根// 先通过pageContext对象获取到request对象,在获取应用的根// 注意:这里强转是因为getContextPath()是HttpServletRequest对象的方法,而先获取到的request对象// 上面对应的EL表达式${pageContext.request.contextPath}

12、常用的隐式对象

(1)pageContext

①这个隐式对象已经讲过了,它是和JSP九大内置对象的pageContex是同一个对象;最主要的用法就是用来获取应用的根:${pageContext.request.contextPath}

(2)param

①假如前端发送请求(通过form表单或者地址栏上直接提交数据):http://localhost:8080/jsp/15.jsp?username=lisi 我们要想获得前端提交的数据,就要调用内置对象request的getParameter方法;那如果使用EL表达式呢?需要使用隐含对象"param.用户名"的形式:

用户名:
用户名:${param.username}

 (3)paramValues

①那如果提交的数据是一个复选框(checkbox)呢?同一组的checkbox的name是一样的;例如:http://localhost:8080/jsp/15.jsp?aihao=smoke&aihao=drink&aihao=tangtou--%>;此时在按照原来的方式进行访问,获取的是一维数组当中的第一个元素,这就需要paramValues 隐式对象了!

爱好:${param.aihao} 
爱好:

②使用paramValues获取的是一个字符串的一维数组

${paramValues.aihao}

③得到这个一维数组后,就可以通过下标的方式进行获取数组中的元素! 

爱好:${paramValues.aihao[0]}、${paramValues.aihao[1]}、${paramValues.aihao[2]} 

 (4)initParam

①ServletContext是Servlet上下文对象,对应的JSP九大内置对象之一是:application

②取出的是标签中配置的属性,属于上下文初始化参数(全局的)

             pageSize 20         pageNum 5    

③web.xml文件配置好以后进行输出

每页显示的记录条数: 
页码:
-------------------------等价于---------------------------------每页显示的记录条数:${initParam.pageSize}
页码:${initParam.pageNum}

13、EL表达式的运算符

(1)算术运算符:+(重点)、-、*、/、%

+在这里只做求和运算,不会做字符串拼接;如果是数字类型的字符串会自动转换为数字进行运算;如果不是数字类型的字符串会报500错误,并抛出NumberFormatException异常。

${10 + 20} 
30 ${10 + "20"}
30${10 + "abc"}
500错误

(2)关系运算符:== 、eq(相当于==,重点)、 !=、 >、 >=、 <、 <=

使用==实际上会自动调用equals方法;所以比较的是内容,不是内存地址。实际上eq、!=底层也会调用equals方法。

${"abc" == "abc"} 
true${"abc"} == ${"abc"}
abc == abc${k1 == k2}
true${o1 == o2}
false${a == b}
true

(3)逻辑运算符:! && || not and or

! 和 not 效果一样的,都是取反。

Student stu1 = new Student("110", "警察");Student stu2 = new Student("110", "警察");${!(stu1 eq stu2)}
false${not(stu1 eq stu2)}
false

(4)取值运算符:[ ]和.

前面代码经常在用了,就是取值的作用。

(5)empty运算符 (重点)

empty运算符的结果是boolean类型 ;判断是否为空,如果为空,结果是true。如果不为空,结果是false。

${empty param.username} 
${!empty param.username}
取反${not empty param.username}
取反${param.password == null}
true ${empty param.password == null}
false

(6)条件运算符:? :

和empty联合使用,可以实现一个很简单的逻辑业务。

${empty param.username ? "对不起,用户名不能为空!" : "欢迎访问!!!!" }