EL表达式与JSTL标准标签库

1. EL表达式

1.1. 什么是EL表达式

EL全名为Expression Language,它主要用于替换JSP页面中的脚本表达式<%= %>,从各种类型的Web域中检索Java对象、获取数据。它可以很方便地访问JavaBean属性,访问数组,访问List集合和Map集合等。

EL表达式借鉴了JavaScript多类型转换无关性的特点,在使用EL从scope中得到参数时可以自动转换类型,因此对于类型的限制更加宽松。Web服务器对于request域中的属性是以Object类型来存储的,在得到该属性时使用的Java语言脚本就应该是(Object)request.getAttribute("xxx"),它对于实际应用还必须进行强制类型转换。而EL就将用户从这种类型转换的繁琐工作脱离出来,允许用户直接使用EL表达式取得的值,而不用关心它是什么类型的。

1.2. EL表达式语法

1.2.1. 语法结构

${requestScope.user.age}

所有的EL都是这么写的:${***},上述例子的意思是从request域对象中,取得user这个对象的年龄。如果我们不使用EL表达式,而是采用JSP Scriptlet的写法,那么应该如下:

User user = (User)request.getAttribute("user");
int age = user.getAge();

可以看到,不使用EL表达式,我们需要从request域中取出,再进行类型转换,非常麻烦。EL表达式简化了这些步骤,更加方便和简洁。

1.2.2. [].运算符

EL提供[]和.两种运算符来导航数据。如下例:

${requestScope.user.sex}
${requestScope.user["sex"]}

这两者是等价的。如何使用这两种方法需要知道以下三点:
(1) [].可以同时混合使用
假设request域对象中放了一个User类的数组,我们使用EL表达式获取到了第2个人的年龄:

<%
User user1 = new User("小明",18);
User user2 = new User("小亮",17);
User user3 = new User("小红",20);
User[] users = new User[]{user1,user2,user3}; 
request.setAttribute("users", users);
%>
${requestScope.users[1].age}

(2) 当要存取的属性名称中包含一些特殊字符,比如点号.或者横杠-等非字母或数字的符号,就必须要使用[]
比如,${user.my-age}这种用法不正确,应当使用${user["my-age"]}
(3) 使用[]可以动态获取数据
比如:

${requestScope.user[data]}

此时,data是一个变量,假如data=”age”,那么上述语句就等价于${requestScope.user.age},假如data=”name”,它就等价于${requestScope.user.name}
因此,要动态取值时,就要使用[]来做,使用点号.无法做到。

1.3. 隐式对象

JSP本身定义了9个内置对象。而EL表达式也定义了11个隐式对象,使用这些隐式对象可以很方便地获取Web开发中的一些常见对象,并读取这些对象的数据。比如,在上文中我们已经使用了requestScope这个隐式对象。所有的隐式对象如下:

隐含对象说明
pageScope代表page域,可以用来获取page域中的属性
reqeustScope代表reqeust域,可以用来获取reqeust域中的属性
sessionScope代表session域,可以用来获取session域中的属性
applicationScope代表application域,可以用来获取application域中的属性
pageContext代表pageContext对象,注意和pageScope进行区分
param代表请求参数组成的map集合${param.username},如同request.getParameter(String name)。回传String类型的值
paramValues代表请求参数组成的map集合,但是此集合的value是String[],用来获取一个多值的param.如同request.getParameterValues(String name)。回传String[]类型的值
header获取所有HTTP请求字段的map对象。如同request.getHeader(String name)。回传String类型的值
headerValues同上,获取请求头组成的map,但是value是一个String[]。如同request.getHeaders(String name)。回传String[]类型的值
cookie获取cookie组成的map对象,此map的值是一个cookie对象,${cookie.cookieName.value}返回cookie的值
initParam以map封装的web.xml中配置的整个web应用的初始化参数。如同ServletContext.getInitParameter(String name)。回传String类型的值

下面重点介绍几种隐式对象的用法,其他的都是类似的,不再一一赘述。

1.3.1. 属性(Attribute)与范围(Scope)

与范围有关的EL隐式对象有四个,分别是:pageScoperequestScopesessionScopeapplicationScope,它们和JSP中的pageContextrequestsessionapplication一样。不过要注意的是,这四个隐式对象只能用来取得范围属性值,即JSP中的getAttribute(String name),却不能取得其他相关信息,比如它不能获取请求参数。

举例,比如我们在request中放入一个属性,名称为name,在JSP中使用request.getAttribute("name")来取得name的值,但是在EL中,则是使用${requestScope.name}来取得其值。

【注意】如果不写范围,直接获取name,${name},那么EL会先去pageScope中找,再去requestScope,sessionScope和applicationScope中找,直到找到这个属性,如果没有找到,则不返回任何值,但是不会报错。

1.3.2. param和paramValues

在取得用户参数时,通常使用的是:

request.getParameter(String name);
request.getParameterValues(String name);

在EL中,则可以使用param和paramValues两者来取得数据。

${param.name}
${paramValues.name}

1.3.3. pageContext

我们可以使用${pageContext}来取得其他有关用户要求或页面的详细信息。比较常用的如下:

表达式说明
${pageContext.request.queryString}取得请求的参数字符串
${pageContext.request.requestURL}取得请求的URL,但不包括请求之参数字符串
${pageContext.request.method}取得HTTP的方法(GET、POST)
${pageContext.request.protocol}取得使用的协议(HTTP/1.1、HTTP/1.0)
${pageContext.request.remoteAddr}取得用户的IP地址
${pageContext.session.id}取得session的ID

1.4. EL算术运算

EL支持算术运算,下表是它所支持的算术运算符:

操作符说明
+数学运算符,加操作
-数学运算符,减操作,或者对一个值取反
*数学运算符,乘操作
/或者div数学运算符,除操作
%或者mod数学运算符,取余操作

我们可以这样使用它们:

${1.2+90}
${(requestScope.index + 30)*2}

1.5. EL关系运算符

EL中的关系运算符如下:

运算符说明举例
== 或 eq判断符号左右两端是否相等,如果相等返回 true ,否则返回 false${5 == 5}或者${5 eq 5}
!= 或 ne判断符号左右两端是否不相等,如果不相等返回 true ,否则返回 false${5 != 5}或者${5 ne 5}
< 或 lt判断符号左边是否小于右边,如果小于返回 true ,否则返回 false${3 < 5}或者${3 lt 5}
> 或 gt判断符号左边是否大于右边,如果大于返回 true ,否则返回 false${3 > 5}或者${3 gt 5}
<= 或 le判断符号左边是否小于或者等于右边,如果小于或者等于返回 true ,否则返回 false${3 <= 5}或者${3 le 5}
>= 或 ge判断符号左边是否大于或者等于右边,如果大于或者等于返回 true ,否则返回 false${3 >= 5}或者${3 ge 5}

要注意的是,使用EL关系运算符时,不能够写成:

${param.index1} == ${param.indexs}

而应该写成:

${param.index1 == param.index2}

1.6. EL逻辑运算符

运算符说明
&& 或 and与操作赋。如果左右两边同为 true 返回 true ,否则返回 false
||或 or或操作赋。如果左右两边有任何一边为 true 返回 true ,否则返回 false
! 或 not非操作赋。如果对 true 取运算返回 false ,否则返回 true

另外
(1) EL中也支持三目运算符:

${A?B:C}

(2) Empty运算符
用来对一个空变量值进行判断 : null 、一个空 String 、空数组、 空 Map 、没有条目的 Collection 集合

${empty var}

2. JSTL标准标签库

  1. 先导taglibs-standrad-impl-1.2.1.jar以及taglib-standrad-spec-1.2.1.jar
  2. 然后引用<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

2.1. JSTL介绍

jsp standard tag libaray,即jsp标准标签库。
jstl是由Apache的Jakarta小组开发的,属于开放源代码的标签库,jstl至少要运行在支持jsp1.2和Servlet2.3规范的容器上。

我们为什么需要JSTL标签呢?

(1)在应用程序服务器之间提供统一的接口,从而提供了web应用在不同服务器的移植
(2)简化jsp与web应用程序的开发
(3)减少jsp中java片段的代码,可以达到在jsp页面中没有任何java代码,代码更加简洁
(4)提高jsp开发速度,缩短开发周期

在这里要知道的是,使用JSTL标签,必须先在项目中引入它的标签库,在MyEclipse中新建项目时它默认会直接引入JSTL标签库,如下图,我引入的是JSTL 1.2.1版本。
JSTL标签库

2.2. 核心标签

jstl的核心标签,也就是c标签,它是最常用的jstl标签。在jsp文件中使用核心标签,需要在文件开头使用tablib指令引入核心标签库,语法如下:

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

之后就可以使用c标签了。

2.2.1. 一般用途的标签

在jstl中,最常用的核心标签有:<c:out><c:set><c:remove><c:catch>

2.2.1.1. <c:out>标签

<c:out>用于把计算的结果输出到JspWriter对象。
(1)简单地输出一个’Hello,World!’.

<c:out value="Hello,World!"></c:out>

这句话就相当于在jsp写如下java片段:

<%
    out.println("Hello,World!");
%>

(2)输出request域对象中的值
假设我们在request域对象中放入下述属性:

<%
    request.setAttribute("abc","request");
%>

这时我们可以这样输出:

<c:out value="${abc}"></c:out>

其实这里用到了JSP的EL表达式。
(3)request,session,application,pageContext域对象的优先顺序
假如,我们在request,session,application,pageContext域对象中都放入了key=abc的属性,那么输出是怎么样的,比如,我们这么写:

<%
request.setAttribute("abc", "request");
session.setAttribute("abc", "session");
application.setAttribute("abc", "application");
pageContext.setAttribute("abc", "pageContext");
%>

这时候我们再使用标签输出,会输出什么呢?

<c:out value="${abc}"></c:out>

答案是输出pageContext,它查找的优先顺序是:pageContext > request > session > application
(4)c:out标签的其他属性
request中放如下属性:

<%
request.setAttribute("url","<a href="www.baidu.com">Baidu</a>");
%>

jsp页面做如下输出:

<c:out value="${url}" default="没有值" escapeXml="false"></c:out>

它会在页面输出一个超链接,而不是一串文本。
这里default属性用于指定域对象中没有值时的默认值。
escapeXml属性用于指定是否按照html样式输出,默认是true,代表以文本形式输出

(5)输出JavaBean的属性
比如,我们的request域对象中放入了一个User对象,如下:

<%
User user = new User();
user.setName("Gavin");
user.setAge(12);
request.setAttribute("u", user);    
%>

现在我们要输出u的name和age属性:
写法如下:

 <c:out value="${u.name }"></c:out>
  <c:out value="${u.age}"></c:out>

这里可以使用u.name和u.age属性是因为User类中有getName和getAge方法

2.2.1.2. <c:set>标签
  1. 给某个范围内设置某个值
    用于在某个范围(page,request,session,application等)中设置某个值
    用法如下:
<c:set var="abc" value="China,北京" scope="request"></c:set>

scope属性指定将该值放在哪个域对象中。
这句话等价于:

 request.setAttribute("abc","China,北京");

然后我们将这个属性值输出:

<c:out value="${abc }"></c:out>
  1. 修改对象的某个属性值
<c:set property="name" value="value" target="${user}"></c:set>

property:代表要修改的属性名
value:代表修改后的值
target:代表要修改的对象

2.2.1.3. <c:remove>标签

这个标签用于删除某个变量或者属性,比如我们要删除request对象中名字为’a’的属性:

<c:remove var="a" scope="request"/>
2.2.1.4. <c:catch>标签

这个标签用于捕获嵌套在它内部的标签抛出的异常

<c:catch var="myexception">
    <%
        int i=8/0;
     %>
</c:catch>
<c:out value="${myexception}"></c:out>

2.2.2. 条件标签

2.2.2.1. <c:if>标签

该标签用于进行条件判断,如果它的test属性为true,那么就去处理它的body。
(1)判断一个字符串
request域对象中放入:

request.setAttribute("a", "hello");

判断如果a为’hello’则输出’ok!’,否则就输出’no!’,如下:

<c:if test="${a=='hello' }">
    ok!
 </c:if>
 <c:if test="${a!='hello' }">
    no!
 </c:if>

要注意的是,这里没有if-else多分支语句,所以只能使用两个if语句去判断。

(2)判断一个JavaBean对象的属性

request域对象中放如下User对象:

<%          
User user = new User();
user.setAge(28);
request.setAttribute("u", user);
%>

判断u的年龄:

<c:if test="${u.age > 27 }">
    User的年龄大于27
 </c:if>

(3)保存判断后的结果

<c:if test="${u.age > 27 }" scope="page" var="flag">
	User的年龄大于27
</c:if>

test:判断条件
scope:将判断的结果保存在指定的作用域中
var:指定key值

2.2.2.2. <c:choose><c:when><c:otherwise>标签

【1】<c:choose>用于条件的选择,它和<c:when><c:otherwise>一起使用。
【2】<c:when>它代表了<c:choose>的一个条件分支,使用它的限制条件:

  • (1)必须以<c:choose>作为它的父标签
  • (2)必须在<c:otherwise>之前出现

【3】<c:otherwise>代表了<c:choose>的最后一个分支,使用它的限制条件:

  • (1)必须以<c:choose>作为它的父标签
  • (2)必须是<c:choose>的最后分支出现

其实它类似于JavaSE中的switch-case-default语句,看下述例子:

<body>
    <%
        User user = new User();
        user.setName("Gavin");
        user.setAge(22);
        request.setAttribute("u",user);
     %>
     <c:choose>
        <c:when test="${u.age<10}">
            用户的年龄小于10</c:when>
        <c:when test="${u.age>=10 and u.age<20 }">
            用户的年龄不小于10岁,但小于20</c:when>
        <c:otherwise>
            用户的年龄大于20</c:otherwise>
     </c:choose>
  </body>

2.2.3. 循环标签

2.2.3.1. <c:forEach>标签

<c:forEach>在一个Collection中迭代计算他的body内容,或是重复迭代固定的次数。
(1)最简单的迭代标签

<c:forEach var="i" begin="1" end="10">
        <c:out value="${i}"></c:out>-->
</c:forEach>

在这里,var代表当前条目的变量名称,begin指的是开始的元素,end指结束的元素,两者都包含在内。
它的输出是这样的:
在这里插入图片描述
另外,我们也可以通过step属性来指定步长,如下:

<c:forEach var="i" begin="1" end="10" step="2">
        <c:out value="${i}"></c:out>-->
</c:forEach>

这里表示输出的是1到10之间的所有奇数。
(2)迭代一个ArrayList集合

假设我们在requestScope中放入了一个ArrayList,中间加入的是User对象,如下:

<%
ArrayList<User> array = new ArrayList<User>();
User user1 = new User();
user1.setName("u1");
user1.setAge(20);

User user2 = new User();
user2.setName("u2");
user2.setAge(21);

User user3 = new User();
user3.setName("u3");
user3.setAge(22);

array.add(user1);
array.add(user2);
array.add(user3);

request.setAttribute("users", array);
%>

我们利用forEach标签可以很简单的输出这个ArrayList集合中的内容,如下:

<c:forEach items="${users}" var="user">
    <c:out value="${user.name}"></c:out>
    <c:out value="${user.age}"></c:out>
    <br>
</c:forEach>

这里用items属性来指定要循环的集合。
另外,我们也可以在这里指定beginendstep属性,来指定输出哪些对象。
还可以指定varStatus:封装当前遍历状态的详细信息。
(3)迭代一个HashMap
假设我们上面的User都是放在HashMap中的,如下:

<%
Map<String,User> map = new HashMap<String,User>();
User user1 = new User("小明",12);
User user2 = new User("小强",13);
User user3 = new User("小华",14);
map.put("aa", user1);
map.put("bb", user2);
map.put("cc", user3);
request.setAttribute("persons",map);
%>

那么,我们可以通过如下方式迭代:

<c:if test="${empty persons}">
    没有人!
</c:if>
<c:forEach items="${persons}" var="person">
    key = ${person.key};&nbsp;value=${person.value.name},${person.value.age}<br>
</c:forEach>

其实,与ArrayList的迭代方式类似,只是,这里通过var.key返回HashMap中的Key值,通过var.value返回HashMap中的Value值,Value也可以是一个对象,如本例。

2.2.3.2. <c:forTokens>标签

<c:forTokens>标签可以根据某个分隔符分隔指定字符串。
比如:

<%
    request.setAttribute("abc", "12;56;你好;Gavin");
%>
<c:forTokens items="${requestScope.abc}" delims=";" var="temp">
    ${temp}
</c:forTokens>

另外,这里也可以指定begin,end和step属性。与前述类似。

2.2.4. Url相关的标签

Url标签就是和页面导航,重定向,资源获得,参数传递相关的标签。

主要有:
(1)<c:param>标签,用来给包含或者重定向的页面传递参数
(2)<c:redirect>标签,重定向至一个新的URL
(3)<c:url>标签,使用可选的查询参数来创造一个URL

2.2.5. 重定向标签

<c:redirect url="/index.jsp"></c:redirect>

直接重定向到指定的页面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值