EL表达式

1.1 为什么需要EL表达式和JSP标签

  JSP的产生在一定程度上将Servlet中负责表现的功能抽取了出来,但JSP页内嵌入的Java代码也破坏了页面中负责表现的页面结构,特别是当运算逻辑稍微复杂一点的话,那么JSP页面中大量的Java代码增加了页面维护的难度。

  所以使用简单的标签来表现复杂的逻辑以及使用简单的形式表现运算的关系就是EL表达式和JSP标签出现的原因。

1.2. 什么是EL表达式

  一套简单的运算规则,用于给JSTL标签的属性赋值,也可以直接用来输出而脱离标签单独使用。

1.3. EL表达式的作用

  EL(Expression Language)是从 JavaScript 脚本语言得到启发的一种表达式语言,它借鉴了 JavaScript 多类型转换无关性的特点。

  在使用 EL 从scope 中得到参数时可以自动转换类型,因此对于类型的限制更加宽松。 Web 服务器对于 request 请求参数通常会以 String 类型来发送,在得到时使用的 Java 语言脚本就应该是request.getParameter(“XXX”) ,这样的话,对于实际应用还必须进行强制类型转换。而 EL 就将用户从这种类型转换的繁琐工作脱离出来,允许用户直接使用EL 表达式取得的值,而不用关心它是什么类型。

1.4. 访问Bean属性

  在JSP页面中经常要输出系统定义的对象的属性,而按照以往的写法需要自己去对象域中获取、转换再输出,使用EL表达式可以非常明显的简化过程

  Bean:指的是一个公共的类有包有无参构造实现以序列化接口,按照固定的方式提供属性的get/set访问方式。针对这种特殊类型的属性访问使用EL表达式实现有两种方式,如下。

方式一:${对象名.属性名}

  ${user.name}

  执行的过程为:从pageContext、request、session、application中依次查找绑定名为“user”的对象,找到后调用“getName”方法,将返回值输出。

  假定在session中绑定了一个对象,如下:

  User obj = new User(1,“胡萝卜”);

  session.setAttribute(“user”,obj);

  那么${user.name}****等价于下面代码:

<%
User u = (User)session.getAttribute(“user”);
out.print(u.getName();
%>

  这种繁琐的取值,转换,输出的过程就都由系统代劳了。而且表达式比以上繁琐代码更会处理null。

  如果没有为name属性赋过值,页面输出“”,不会输出null。如果取值时绑定名写错,如**\({obj.name},页面也会输出“”**,而不是报空指针异常。但属性名写错会报错,如\){user.naaa}.

方式二:${对象名[“属性名”]}

表达式也支持属性名的动态读取,这时需要采用方式二${user[“name”]}的形式。

  假定在Servlet中有如下代码:

User obj = new User(1,”胡萝卜”);
session.setAttribute(“user”,obj);
session.setAttribute(“pName”,”id”);

  在JSP中编写如下代码会输出“1”:

     ${sessionScope.user[“id“]}

  在JSP中编写如下代码也会输出“1”:

     ${sessionScope.user[sessionScope.pName]}

  如果pName在绑定时不指定id,而是name,那么这个表达式就会输出“胡萝卜“,所以这种写法可以认为是表达式中有一个变量。sessionScope.pName 等价于 session.getAttribute(“pName”)。

   如果User类型的定义如下:

package bean;
public class User {
private String name;
private int age;
private String[] interests;
private String gender;
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String[] getInterests() {
return interests;
}
public void setInterests(String[] interests) {
this.interests = interests;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

  那么对于interests这个数组属性的值可以使用如下表达式访问:

         ${user.interests[0]}

1.5. 指定对象的查找范围

  在书写表达式时,如果没有指定搜索范围,那么系统会依次调用pageContext、request、session、application的getAttribute()方法。这样不限定查找范围的代码不利于排错,所以这种取值的操作可以限定对象的查找范围。

  如:

    ${sessionScope.user.name}

  一旦指定了对象所在的范围,那么只会在范围内查找绑定对象,不会在找不到的时候再去其他区域中查找了。

  sessionScope的位置还可以填写pageScope、requestScope、applicationScope

1.6. 使用EL表达式进行计算

  使用EL表达式可以单独进行运算得出结果并直接输出,如下代码所示,EL进行算术运算,逻辑运算,关系运算,及empty运算

  空运算主要用于判断字符串,集合是否为空,是空或为null及找不到值时都会输出true。

<%request.getSession().setAttribute("sampleValue", new Integer(10));%>

${sessionScope.sampleValue}                         // 显示 10
${sessionScope.sampleValue + 12} <br> // 显示22
${(sessionScope.sampleValue + 12)/3} <br> // 显示7.3
${(sessionScope.sampleValue + 12) /3==4} <br> // 显示 false
${(sessionScope.sampleValue + 12) /3>=5} <br> // 显示 true
<input type="text" name="sample1" value="${sessionScope.sampleValue + 10}">
// 显示值为20的 Text 控件
${empty null} //显示true

1.7. 使用EL表达式获取请求参数值

  以下两种写法分别等价:

    \({param.username} 与 request.getParameter(“username”);**
    **\){paramValues.city} 与request.getParameterValues("city");

EL运行原理

JSTL

2.1. 什么是JSTL

  Sun 公司 Java 标准规范的 JSTL 由 apache组织负责维护。作为开源的标准技术,它一直在不断地完善。 JSTL 的发布包有两个版本: **Standard-1.0 Taglib **、 Standard-1.1 Taglib ,它们在使用时是不同的。

  Standard-1.0 Taglib ( JSTL1.0 )支持 Servlet2.3 和 JSP1.2 规范, Web 应用服务器 **Tomcat4 **支持这些规范,而它的发布也在 Tomcat 4.1.24 测试通过了。

  Standard-1.1 Taglib ( JSTL1.1 )支持 Servlet2.4 和 JSP2.0 规范, Web 应用服务器 **Tomcat5 **支持这些规范,它的发布在 Tomcat 5.0.3 测试通过了。

2.2. 如何使用JSTL

  将标签库对应的jar包拷贝到WEB-INF/lib目录下,以便于系统可以加载所需要的类。使用taglib指令在页面上引入标签的命名空间和前缀,帮助系统定位对应的类。

如:

   <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

JSTL运行原理

2.3. 核心标签

if标签

   JSP页面的显示逻辑中也经常需要进行条件判断,<c:if>标签可以构造简单的“if-then”结构的条件表达式,如果条件表达式的结果为真就执行标签体部分的内容。<c:if>标签有两种语法格式:

   

  • 语法1,没有标签体的情况:

       <c:if test="testCondition" var="varName"  [scope="{page|request|session|application}"] />

       
  • 语法2,有标签体的情况,在标签体中指定要执行的内容:

      <c:if test="testCondition" [var="varName"] [scope="{page|request|session|application}"]>

       body content

      </c:if>

      <c:if>标签的属性说明

      如表所示:
属性名 是否支持EL 属性类型 属 性 描 述
test true boolean 决定是否处理标签体中的内容的条件表达式
var false String 用于指定将test属性的执行结果保存到某个Web域中的某个属性的名称
scope false String 指定将test属性的执行结果保存到哪个Web域中

  对于语法2,如果指定了<c:if>标签的scope属性,则必须指定var属性

  使用if标签实现属性判断后的输出。代码如下所示:

<%
User user = new User();
user.setName("胡萝卜");
user.setGender("f");
request.setAttribute("user",user);
%>
姓名:${user.name}<br/>
性别:
   <c:if test="${user.gender =='m'}" var="rs" scope="request">男</c:if>
 <c:if test="${!rs}">女</c:if>

choose标签

  <c:choose>标签用于指定多个条件选择的组合边界,它必须与<c:when>和<c:otherwise>标签一起使用。使用<c:choose>,<c:when>和<c:otherwise>三个标签,可以构造类似 “if-else if-else” 的复杂条件判断结构。

  <c:choose>标签没有属性,在它的标签体内只能嵌套一个或多个<c:when>标签0个或一个<c:otherwise>标签,并且同一个<c:choose>标签中的所有<c:when>子标签必须出现在<c:otherwise>子标签之前。

  • 如果<c:choose>标签内嵌套一个<c:when>标签和<c:otherwise>标签,就相当于“if-else”的条件判断结构;
  • 如果<c:choose>标签内嵌套多个<c:when>标签和一个<c:otherwise>标签,就相当于“if-else if-else”标签。

 

  <c:when>标签只有一个test属性,该属性的值为布尔类型。test属性支持动态值,其值可以是一个条件表达式,如果条件表达式的值为true,就执行这个<c:when>标签体的内容。<c:when>标签体的内容可以是任意的JSP代码。<c:otherwise>标签没有属性,它必须作为<c:choose>标签的最后分支出现

  当JSP页面中使用<c:choose>标签时,嵌套在<c:choose>标签内的test条件成立的第一个<c:when>标签的标签体内容将被执行和输出。当且仅当所有的<c:when>标签的test条件都不成立时,才执行和输出<c:otherwise>标签的标签体内容。如果所有的<c:when>标签的test条件都不成立,并且<c:choose>标签内没有嵌套<c:otherwise>标签,则不执行任何操作

  使用choose标签简化多个if标签的判断。代码如下所示:

<%
User user = new User();
user.setName("胡萝卜");
user.setGender("x");
request.setAttribute("user",user);
%>
性别:
<c:choose>
<c:when test="${user.gender == 'm'}">男</c:when>
<c:when test="${user.gender =='f'}">女</c:when>
<c:otherwise>未知</c:otherwise>
</c:choose>

forEach标签

 JSP页面的显示逻辑中也经常需要对集合对象进行循环迭代操作,<c:forEach>标签用于对一个集合对象中的元素进行循环迭代操作,或者按指定的次数重复迭代执行标签体中的内容。<c:forEach>标签有两种语法格式 

  • 语法1,在集合对象中迭代:

    **

    <c:forEach [var="varName"]

      items="collection"

      [varStatus="varStatusName"]

      [begin="begin"] [end="end"] [step="step"]>

      body content

    </c:forEach>

    **

  • 语法2,迭代固定的次数:

    **

    <c:forEach [var="varName"]

      [varStatus="varStatusName"]

      begin="begin" end="end" [step="step"]>

      body content

    </c:forEach>

    **

  <c:forEach>标签的属性

属性名 是否支持EL 属性类型 属 性 描 述
var false String 指定将当前迭代到的元素保存到page这个Web域中的属性名称
items true 任何支持的类型 将要迭代的集合对象
varStatus false String 指定将代表当前迭代状态信息的对象保存到page这个Web域中的属性名称
begin true int 如果指定items属性,就从集合中的第begin个元素开始进行迭代,begin的索引值从0开始编号;如果没有指定items属性,就从begin指定的值开始迭代,直到end值时结束迭代
end true int 参看begin属性的描述
step true int 指定迭代的步长,即迭代因子的迭代增量

 在使用<c:forEach>标签时,需要注意如下几点说明:

  •    如果指定begin属性,其值必须大于或等于零;
  •    如果指定步长(step属性),其值必须大于或等于1;
  •    如果items属性的值为null,则要处理的集合对象为空,这时不执行迭代操作;
  •    如果指定的begin属性的值大于或等于集合对象的长度,不执行迭代操作;
  •    如果指定的end属性的值小于begin属性的值,不执行迭代操作;

  <c:forEach>标签的items属性的值支持下面的数据类型

  任意类型的数组

  •   java.util.Collection

  •   java.util.Iterator

  •   java.util.Enumeration    

  •   java.util.Map

  •   

  •   String

  •   java.sql.ResultSet

       items属性还支持与数据库有关的数据类型java.sql.ResultSet(包括javax.sql.RowSet)。对字符串的迭代操作通常使用<c:forTokens>标签或JSTL函数,例如fn:split和fn:jion。

使用forEach标签完成对集合的遍历输出

  使用forEach标签完成对集合的遍历输出。

  其中items属性为要遍历的集合var属性为每次取出来的一个对象varStatus指定当前迭代的状态。代码如下:

<!-- forEach
Map map = new HashMap();
for(Object itr : interests) {
Integer index = map.get("index");
if(index==null) {
map.put("index",0);
} else {
map.put("index",index+1);
}
map.put("其他","");
}
每次循环JSTL会创建一个对象,用来存储循环次数等值。
可以通过varStatus属性声明该对象的变量,
从而来访问该对象,获取循环次数等值。
--> <c:forEach items="${stu.interests }"
var="itr" varStatus="s">
${itr },${s.index },${s.count }<br>
</c:forEach>

迭代Collection类型的集合对象

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=gb2312" %>
<%@ page import="java.util.*,org.it315.UserBean" %>
<%
Collection users = new ArrayList();
for(int i=0; i<5; i++)
{
UserBean user = new UserBean();
user.setUserName("user" + i);
user.setPassword("guess" + i);
users.add(user);
}
session.setAttribute("users", users);
%>
<div style="text-align:center">User List
<table border="1">
<tr><td>用户名</td><td>密码</td></tr>
<c:forEach var="user" items="${users}">
<tr>
<td>${user.userName}</td><td>${user.password}</td>
</tr>
</c:forEach>
</table></div>

迭代Map对象

  使用<c:forEach>标签迭代Map类型的集合对象时,迭代出的每个元素的类型为Map.Entry,Map.Entry代表Map集合中的一个条目项,其中的getKey()方法可获得条目项的关键字,getValue()方法可获得条目项的值。

  EL中的requestScope隐含对象代表request作用域中的所有属性的Map对象,所以我们可以使用<c:forEach>标签迭代输出EL中的requestScope隐含对象中的所有元素,如例所示。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=gb2312" %>
<%
request.setAttribute("attr1","value1");
request.setAttribute("attr2","value2");
%>
<div style="text-align:center">Properties(Map)
<table border="1">
<tr><td>Map的关键字</td><td>Map的对应关键字的值</td></tr>
<c:forEach var="entry" items="${requestScope}">
<tr><td>${entry.key}</td><td>${entry.value}</td></tr>
</c:forEach>
</table></div>

获取迭代的状态信息

  不管是迭代集合对象,还是迭代指定的次数,在迭代时都可以获得当前的迭代状态信息

  <c:forEach>标签可以将代表当前迭代状态信息的对象保存到page域中,varStatus属性指定了这个对象保存在page域中的属性名称

  代表当前迭代状态信息的对象的类型javax.servlet.jsp.jstl.core.LoopTagStatus,从JSTL规范中可以查看到这个类的详细信息,其中定义了如下一些方法

  • public java.lang.Integer getBegin()

    返回为标签设置的begin属性的值,如果没有设置begin属性则返回null

  • public int getCount()

    返回当前已循环迭代的次数

  • public java.lang.Object getCurrent()

    返回当前迭代到的元素对象

  • public java.lang.Integer getEnd()

    返回为标签设置的end属性的值,如果没有设置end属性则返回null

  • public int getIndex()

    返回当前迭代的索引号

  • public java.lang.Integer getStep()

    返回为标签设置的step属性的值,如果没有设置step属性则返回null

  • public boolean isFirst()

    返回当前是否是第一次迭代操作

  • public boolean isLast()

    返回当前是否是最后一次迭代操作

下面是一个获取迭代状态信息的例子程序。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=gb2312" %>
<%@ page import="java.util.*,org.it315.UserBean" %>
<%
Collection users = new ArrayList();
for(int i=0; i<6; i++)
{
UserBean user = new UserBean();
user.setUserName("user" + i);
user.setPassword("guest" + i);
users.add(user);
}
session.setAttribute("users", users);
%>
<div style="text-align:center">User List
<table border="1">
<tr><td>用户名</td><td>密码</td><td>index</td>
<td>count</td><td>first?</td><td>last?</td></tr>
<c:forEach var="user" items="${users}" varStatus="sta" begin="1" step="2">
<tr>
<td>${user.userName}</td><td>${user.password}</td>
<td>${sta.index}</td><td>${sta.count}</td>
<td>${sta.first}</td><td>${sta.last}</td>
</tr>
</c:forEach>
</table></div><hr> <div style="text-align:center">迭代固定的次数
<table border="1">
<tr><td>数值</td><td>index</td><td>count</td>
<td>first?</td><td>last?</td></tr>
<c:forEach var="i" varStatus="sta1" begin="101" end="103">
<tr>
<td>${i}</td><td>${sta1.index}</td><td>${sta1.count}</td>
<td>${sta1.first}</td><td>${sta1.last}</td>
</tr>
</c:forEach>
</table></div>

<c:param>标签

  在JSP页面进行URL的相关操作时,经常要在URL地址后面附加一些参数

  <c:param>标签可以嵌套在<c:import><c:url><c:redirect>标签内,为这些标签所使用的URL地址附加参数。<c:param>标签在为一个URL地址附加参数时,将自动对参数值进行URL编码

  例如,

  如果传递的参数值为“中国”,则将其转换为“%d6%d0%b9%fa”后再附加到URL地址后面,这也就是使用<c:param>标签的最大好处。<c:param>标签有两种语法格式:

  •   语法1,使用value属性指定参数的值:

       <c:param name="name" value="value" />

  •   语法2,在标签体中指定参数的值:

    **

        <c:param name="name">

          parameter value

        </c:param>**

    <c:param>标签的属性

属性名 是否支持EL 属性类型 属性描述
name true String 参数的名称
value true String 参数的值

  其它标签我感觉用的比较少就不说了,当用的时候在查找。后面我会写一个如何写自己自定义标签的博客,教大家如何写一个自定义标签。

jsp基础与提高(EL、JSTL)的更多相关文章

  1. JSP基础与提高(一).md

    JSP基础 JSP的由来 1.1. 为什么有JSP规范 Servlet技术产生以后,在使用过程中存在一个很大的问题,即为了表现页面的效果而需要输出大量的HTML标签,这些标签在Servlet中表现为一 ...

  2. 动态页面技术JSP/EL/JSTL

    本节内容: jsp脚本和注释 jsp运行原理 jsp指令(3个) jsp内置/隐式对象(9个) jsp标签(动作) EL技术 JSTL技术 JavaEE的开发模式 动态页面技术:就是在html中嵌入j ...

  3. JSP, EL, JSTL的使用

    JSP基础指令和语法 回顾 在Jsp页面: 只要是Java代码就会原封不动的输出, 如果是html代码,就会转义为 out.write("<html>\r\n") 这样 ...

  4. jsp基础之 jstl

    JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能. JSTL支持通用的.结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签. 除了这些,它还提供 ...

  5. JavaEE之动态页面技术(JSP/EL/JSTL)

    动态页面技术(JSP/EL/JSTL) JSP技术 jsp脚本和注释 jsp脚本: 1)<%java代码%> ----- 内部的java代码翻译到service方法的内部 2)<%= ...

  6. JavaWeb之JSP & EL & JSTL

    JSP & EL & JSTL JSP Java Server Page 什么是JSP 从用户角度看,就是一个网页.从程序员角度看,就是一个Java类,它继承Servlet,所以可以说 ...

  7. JAVA企业级开发--jsp,el,jstl(14)

    三. EL表达式语言 EL 全名为Expression Language.表达式语言.jsp2.0之后才引入的. EL主要作用:替代:<%= %>     out.print(); 获取数 ...

  8. 学会怎样使用Jsp 内置标签、jstl标签库及自定义标签

    学习jsp不得不学习jsp标签,一般来说,对于一个jsp开发者,可以理解为jsp页面中出现的java代码越少,对jsp的掌握就越好,而替换掉java代码的重要方式就是使用jsp标签.  jsp标签的分 ...

  9. JSP表达式语言(EL)

    JSP表达式语言(EL)使得访问存储在JavaBean中的数据变得非常简单.JSP  EL既可以用来创建算术表达式也可以用来创建逻辑表达式.在JSP  EL表达式内可以使用整数型.浮点型.字符串.常量 ...

随机推荐

  1. js验证表单密码、用户名是否输入--JS的简单应用

    在登录.注册时,我们经常会遇到下面这种情况,如果我们没有输入用户名.密码时,系统会弹出提示框.提示框信息提示内容是我们密码没有输入密码或者用户名等.那么这样的弹出框效果是如何实现的呢?文章标题既然与j ...

  2. js 设置下拉框的默认值

    设置下拉框的默认值,直接在option中增加selected就可以了.但是现在要使用JS来设置它的默认值,代码如下: <select name="aaa" id=" ...

  3. iOS多线程开发之NSOperation - 快上车,没时间解释了!

    一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强 ...

  4. 输入三个整数x、y、z,请把这三个数由小到大输出

    题目:输入三个整数x,y,z,请把这三个数由小到大输出. 程序分析:我们想办法把最小的数放到x上,先将x与y进行比较,如果x> y则将x与y的值进行交换,然后再用x与z进行比较,如果x> ...

  5. If I were you

    别让孩子输在起跑线上,这句话有道理吗? 答:和别人比较是人生悲剧的源头. 做哪些事情可以提高生活的品质? 答:定期扔东西. 结婚以后,两个人在一起最重要的是什么? 答:就当这婚还没结呢. 去做你害怕的 ...

  6. SpringMVC配置实例

    一.SpringMVC概述 MVCII模式实现的框架技术 Model--业务模型(Biz,Dao...) View--jsp及相关的jquery框架技术(easyui) Contraller--Dis ...

  7. 【PHP】数据类型转换

    PHP的数据类型转换属于强制转换,允许转换的PHP数据类型有: (int).(integer):转换成整形 (float).(double).(real):转换成浮点型 (string):转换成字符串 ...

  8. BeanFactory VS FactoryBean

    1. BeanFactory BeanFactory定义了 IOC 容器的最基本形式,并提供了 IOC 容器应遵守的的最基本的接口,也就是Spring IOC 所遵守的最底层和最基本的编程规范.在   ...

  9. UnityShader之遮挡透明

    好久没写博客了,最近在学shader,不得不说,shader真的非常美妙,我沉迷其中无法自拔= = 之前做过一个遮挡透明的功能,当物体遮挡住主角时,该物体会变成半透明显示出主角.这次同样是遮挡透明的功 ...

  10. mysql5.7.18的安装与主从复制

    CentOS6.7安装mysql5.7.18 1.  解压到/usr/local目录 # tar -zxvf mysql-5.7.18-linux-glibc2.5-i686.tar.gz -C /u ...