JavaWeb-EL表达式

序言

  JSP中可以使用EL(express language)表达式,EL表达式是用”${}”括起来的脚本,用来更方便地读取对象,EL表达式写在JSP的HTML代码中,而不能写在”<%……%>”引起的JSP脚本中,现在就来了解一下,EL表达式是如何来替代JSP脚本或者JSP行为的。

EL表达式的功能:

  获取4个内置对象(域)中的数据,或自定义对象中的数据,或数组、集合容器中的数据。可以完成非常简单的运行,但它不能完成循环、复杂的判断等功能。使用EL的目的是 简化在JSP中访问变量的方式,简单静态HTML与Java代码的耦合

EL表达式的书写格式:${ 表达式 }

示例如下:

${ “Helloworld” }  //输出字符串常量
${ str }     //输出字符串变量str的值
${ 3 + 2 }   //输出3+2的结果
${ user.name} //输出user对象的name属性
${user[“name”] }  //同上
${ sessionScope[“user”].name } //同上
${user.name}   //访问对象user的getName()方法以得到name成员的值。
${list[1]}     //访问list对象的第二项。
${map[“key”]}  //访问map指定键的值。

【关于[ ]与.运算符】:

EL提供“.“和“[ ]“两种运算符来存取数据:

1、当要存取的属性名称中包含一些特殊字符,如.或?等并非字母或数字的符号,就一定要使用“[ ]“。
例如:
${user.My-Name}应当改为${user["My-Name"] }

2、如果要动态取值时,就可以用“[ ]“来做,而“.“无法做到动态取值。
例如:
${sessionScope.user[data]}中data 是一个变量。

  EL表达式的底层是我们前面学的jsp中的各种对象与方法的操作,只是做了一些优化;有一个很大的优化就是如果找不到数据的话不会返回null或者报异常,而是什么都不显示

  JSP中内置九大对象,所以在<%>java代码中可以直接使用这九大对象,但是EL表达式虽然也在JSP页面中却不可以使用jsp中的九大对象,而是使用el表达式中的11个内置对象

  Jsp中九大内置对象: page request session application(ServletContext) pageContext response config out exception

【EL表达式有11个内置对象】:

  pageScope、requestScope、sessionScope、applicationScope、pageContext、param、paramValues、header、headerValues、cookie、initParam。

pageScope、requestScope、sessionScope、applicationScope代表四个作用域对象。

pageContext  表示的是JSP中内置对象pageContext,能获取request等其他JSP八大内置对象 
param        表示一个请求参数${param.username}等效request.getParameter("username");
paramValues  表示一组请求参数${paramValues.loves}等效request.getParameterValues("loves"); 提交喜爱这种多选框    
header       表示一个请求头${header.referer}等效request.getHeader("referer");
headerValues  表示一组请求头${header.cookie}等效 request.getHeaders("cookie");  获取的请求头参数中的内容是一组内容,比如cookie就有可以是多个cookie一起传过来
cookie       获得cookie对象
initPatam    web项目初始化参数,servletContext.getInitParameter("xxx");

还有一种特殊的用法,直接获取对象变量,

${user.username}

  user为User的一个实例对象,并且存放在page作用域中,上面这句代码的意思是,依次从page、request、session、application作用域查找user对象,直到找到为止,底层使用的是pageContext.findAttribute(); 是一样的效果。


1、 EL表达式获取域对象中的数据

(1) 从四大域中取值

格式:

${xxxxScope.key}

含义:
  使用EL表达式从不同的域中取出数据,需要使用el中的4个内置对象搞定:pageScope、requestScope、sessionScope、applicationScope。在4个EL内置对象xxxxScope取出保存的数据时,相当于使用pageContext.getAttribute(key,scope);取值。

(2) 从不确定域中取值

格式:

${key}

含义:
  如果不知道数据在哪个范围中,这时可以不用指定范围直接书写key值即可${key}。下面代码的底层对应的是 pageContext.findAttribute();。

【小结】:

需求1: 通过el表达式 从指定域中获取数据 (比较和java代码的不同)

需求2: 通过el表达式 从不确定域中获取数据

(3) 应用实例

<body>
  <!-- 需求1: 通过el表达式 从指定域中获取数据 (比较和java代码的不同) -->
  <%
    // 向4个域中设置数据
    //pageContext.setAttribute("address", "上海1"); // 两个参数,默认向page域中放
    //pageContext.setAttribute("address", "上海2", PageContext.REQUEST_SCOPE);
    //pageContext.setAttribute("address", "上海3", PageContext.SESSION_SCOPE);
    //pageContext.setAttribute("address", "上海4", PageContext.APPLICATION_SCOPE);
   %>

   <%--
     <%=pageContext.getAttribute("address1") %>
     <%=pageContext.getAttribute("address", PageContext.REQUEST_SCOPE) %>
     <%=pageContext.getAttribute("address", PageContext.SESSION_SCOPE) %>
     <%=pageContext.getAttribute("address", pageContext.APPLICATION_SCOPE) %>
   <hr/>
   ${pageScope.address1 }
   ${requestScope.address }
   ${sessionScope.address }
   ${applicationScope.address }
    --%>

  <!-- 需求2: 通过el表达式 从不确定域中获取数据 -->
  <%=pageContext.findAttribute("address") %>
  <hr/>
  ${address}
</body>

提示:通过上面的演示,发现EL表达式从四个域中取值,就是在代替使用PageContext中的getAttribute方法取值,底层依然在使用PageContext中的getAttribute方法

【注意】:

1、EL表达式只可以从四大域中获取数据,但不可以存放数据
2、EL表达式中的内容会显示到浏览器上;
3、使用pageContext的getAttribute方法或者findAttribute方法从4个范围中取出数据的时候,如果指定的key不存在会返回null,而使用el表达式取出的时候指定的key不存在,页面上什么都不会显示

【演示】:

<%=pageContext.getAttribute("address",pageContext.PAGE_SCOPE) %> //java代码获取值
<hr/>
${pageScope.address} //EL表达式

页面结果:
这里写图片描述


3、EL表达式获取复杂数据

这里说的复杂数据是指:数组,集合,自定义对象。

(1) EL获取数组中的值

演示代码:
这里写图片描述
页面结果:
这里写图片描述
注意:

1、${arr1}相当于直接调用arr数组对象的toString方法,因为数组中没有重写toString方法所以会显示地址;

2、${arr1[3]} 如果在java中则会报索引越界的异常,但在EL表达式中做了优化,获取不到的数据什么都不会显示。

(2) EL获取List集合中的值

直接看代码:
这里写图片描述
注意:${list1}相当于直接调用list集合对象的toString方法,因为集合中重写了toString方法所以会显示集合的元素。
这里写图片描述

(3) EL获取Map集合中的值

具体代码:
这里写图片描述
运行结果:
这里写图片描述
注意:

1、向map中存放数据map.put(“ccc.ddd.fff”,333),取出整个集合 m a p 1 m a p {map1.ccc.ddd.fff}这种格式则无法显示数据元素,所以使用第二种格式${map1[‘ccc.ddd.fff’]}则可以显示数据

2、两种取数据的格式

方式一:map1.eee 方式二:map1[‘eee’]

方式二使用“[ ]”代替了方式一“.”,又因为是字符串类型所以加上单引号,这样可以避免出错,两种方式看情况选择使用;

3、字符串类型的数据不要以数字开头,比如map.put(“444”,44444)不要使用。

(4) 演示EL获取自定义对象属性值

首先需要在项目中创建一个自定义的对象,这里创建User对象。并且针对User对象中的属性提供相应的get和set方法。
这里写图片描述
这里写图片描述
运行结果:
这里写图片描述
注意:${user1}相当于直接调用自定义类的toString方法,因为自定义类重写了toString方法所以会显示数据

【注意】:

1、在使用EL表达式取出数组,集合,自定义对象中的数据的时候,能够使用.的地方都可以使用中括号。特别是在map集合或者自定义对象中key值或自定义对的属性名中包含多个字符的时候必须使用中括号搞定。

2、在EL表达式中,获取对象的属性的值的时候,其实不是在看这个对象所在的类是否有这个属性,只要这个对象所在的类中有getXxxxx方法,就可以使用EL表达式获取Xxxx值。


4、EL表达式执行运算

(1) 使用EL进行简单的运算

如果指定的范围中的key不存在,这时就不会去使用这个值计算,但是存在的依然会进行运算。

需求1: 将a和b保存到page域中, 使用EL计算 a+b
需求2: 将a和b保存到page域中, 使用EL计算 a+b+c
这里写图片描述
效果:
这里写图片描述

(2) 验证容器或变量是否为null

格式:

 ${ empty  集合或变量等}

如果集合元素的个数为0 或者集合不存在,或者 变量为null 则返回true; 否则返回false。

常用方式——EL中三元运算符:

${empty 对象 ? 表达式1 : 表达式2 }

${not empty 对象 ? 表达式1 : 表达式2 }

需求1: 使用el表达式 判断集合是否为空
需求2: 使用el表达式 判断用户是否存在
这里写图片描述
注意:集合为空或者集合不存在,都是null的意思。
这里写图片描述

(3) EL运算符

运算符允许对数据和文字进行组合以及比较。

EL运算符列表:
这里写图片描述
简单描述:

1)算术运算符有五个:+、-、*或$、/或div、%或mod
2)关系运算符有六个:==或eq、!=或ne、<或lt、>或gt、<=或le、>=或ge
3)逻辑运算符有三个:&&或and、||或or、!或not
4)其它运算符有三个:empty运算符、条件运算符、()运算符

最常用的表达式:
为空判断:${empty param.name}
三元运算:${A?B:C}
算数运算:${A*(B+C)} 

简单实例:
这里写图片描述
结果:
这里写图片描述


5、EL的内置对象

EL表达式它也有自己的内置对象可以直接在EL表达式中使用。

注意:

  如果JSP中既有html代码也有Java代码,会很麻烦,所以我们用 EL表达式 和 JSTL标签 代替Java代码
 (虽然sun公司在设计JSP技术的时候,允许在JSP页面中嵌入java代码,但是这样会导致html、js、java等代码严重的耦合在同一个文件中,导致后期维护十分的麻烦。于是sun公司就将可以在jsp页面上书写的java提前已经封装到对应的标签中,然后让开发者在jsp页面上通过使用标签的方式来使用相应的java代码。其实这些标签的用途并不大,后期如果真的需要功能强大的java代码,需要开发人员自己手动封装标签的

(1) 从不同的域中取值的四个内置对象

格式:
${XXXScope.key}

四个内置对象:
  pageScope
  requestScope
  sessionScope
  applicationScope    

准备工作:

   <%
     pageContext.setAttribute("address", "北京1"); // page
     pageContext.setAttribute("address", "北京2", PageContext.REQUEST_SCOPE); // request
     pageContext.setAttribute("address", "北京3", PageContext.SESSION_SCOPE); // session
     pageContext.setAttribute("address", "北京4", PageContext.APPLICATION_SCOPE); // application(ServletContext)
   %>

 <body>
   <!-- 从四大域中取出数据  -->
   <%
     //pageContext.setAttribute("address", "北京1");//默认page域
     //pageContext.setAttribute("address", "北京2",PageContext.REQUEST_SCOPE);
     //pageContext.setAttribute("address", "北京3",PageContext.SESSION_SCOPE);
     //pageContext.setAttribute("address", "北京4",PageContext.APPLICATION_SCOPE);
   %>

     <%=pageContext.getAttribute("address") %>
     <%=pageContext.getAttribute("address",PageContext.REQUEST_SCOPE) %>
     <%=pageContext.getAttribute("address",PageContext.SESSION_SCOPE) %>
     <%=pageContext.getAttribute("address",PageContext.APPLICATION_SCOPE) %>
   <hr/>

  ${pageScope.address }  
  ${requestScope.address }  
  ${sessionScope.address }  
  ${applicationScope.address }
 <hr/>

Java获取的简化方式: <%=pageContext.findAttribute("address") %> <br/>
EL获取的简化方式: ${address}

演示注意:

1、page和request域从浏览器访问时重写输入地址既可以显示效果,session域需要重启浏览器,application域需要重启服务器才会显示效果;

2、使用Java代码的方式如果获取不到数据输出null,EL表达式的方式则什么都不会显示;

(2) 专门获取浏览器请求服务器时携带参数的2个内置对象

param         获取用户提交的某个数据,针对一key一value   可以理解成:  request.getParameter(name)

paramValues    获取用户提交的某个数据,针对一key多value    可以理解成: request.getParameterValues(name)

实例代码:

<body>
  <%--
     <h4>param对象的使用</h4>
     <%=request.getParameter("username") %>
     ${param.username }
  --%>


   <h4>paramValues对象的使用(多选)</h4>
   <%
      String[] hobbys = request.getParameterValues("hobby");
      out.println(hobbys[0]);
      out.println(hobbys[1]);
   %>

   <hr/>

       ${paramValues.hobby[0]}
       ${paramValues.hobby[1]}
       ${paramValues.hobby[2]}
</body>

运行结果:
这里写图片描述

(3) 专门获取浏览器请求服务器时请求头中数据的2个内置对象

这里写图片描述

(4) cookie它获取到的一个cookie数组

cookie

获取cookie对象: ${cookie.cookie的名称}, 如 ${cookie.username}
获取cookie对象的名称: ${cookie.cookie的名称.name} 如: ${cookie.username.name}
获取cookie对象的值  : ${cookie.cookie的名称.value} 如: ${cookie.username.value}

需求: 在JSP页面向浏览器发送cookie, 在访问时获取cookie中的数据。

02.jsp

 <%
    // 创建cookie
    Cookie cookie = new Cookie("username","fengjie");
    // 设置有效路径
    cookie.setPath("/");
    // 设置最大生存时间
    cookie.setMaxAge(60 * 30);
    // 给浏览器发送cookie
    response.addCookie(cookie);
 %>

03.jsp

<body>
 <h4>获取cookie的内容</h4>
 <%
     Cookie[] cookies = request.getCookies();

     if(cookies!=null){
       for(Cookie cookie : cookies){
         String name = cookie.getName();
         String value = cookie.getValue();
         if("username".equals(name)) {
              out.println(name +"::::"+ value);
         }
       }
     }
%>

 <hr/>
     ${cookie.username }
     ${cookie.username.name }
     ${cookie.username.value }
</body>

结果:
这里写图片描述

(5) 其他对象

pageContext  它就和JSP内置对象pageContext功能一致(重点)
initParam    获取的项目的全局配置参数,类似于ServletContext中的getInitParameter(String name)方法功能(它只能获取到web.xml配置的全局参数,每个servlet单独配置的无法使用initParam获取)。
   <h3>pageContext对象的使用</h3>
   <a href="/d13/03.jsp">03页面</a>
   <%--注意:以后的项目都使用下面这种方式,因为实际开发中项目名会变动 --%>
   <a href="${pageContext.request.contextPath }/03.jsp">03页面</a>
   <%--注意:这种方式不可以,在EL表达式中不可以直接使用request对象,EL表达式中的11个内置对象中没有request内置对象 --%>
   <a href="${request.contextPath }/03.jsp">03页面</a><br/>
   <%=request.getContextPath() %>

   <hr/>
   <%
      HttpServletRequest r = (HttpServletRequest)pageContext.getRequest();
      out.println(r.getContextPath());
   %>

    <hr/>
    el表达式获取项目名:${pageContext.request.contextPath }<br/>
    <%--注意:这种方式不可以,在EL表达式中不可以直接使用request对象 --%>
    el表达式获取项目名:${request.contextPath }

   <h3>initParm对象的使用</h3>
   <%= pageContext.getServletContext().getInitParameter("company") %><br/>
   ${initParm.company }

在web.xml文件中配置全局参数

<context-param>
   <param-name>company</param-name>
   <param-value>传</param-value>
</context-param>

运行结果:
这里写图片描述

总结

jsp的内置对象和EL的内置对象区分:

  jsp页面中的Java代码中可以直接使用的对象称为JSP的内置对象。<% 可以直接使用的对象 %>。EL表达式中11个内置对象,在EL表达式中也可以直接去使用这些对象${ EL的内置对象.key值或者其他的信息 }

注意:EL表达式的作用就是从四大域中取数据,前提是先有数据向域中存放;

猜你喜欢

转载自blog.csdn.net/weixin_39190897/article/details/82559300