jsp基础与提高(EL、JSTL)
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属性则返回nullpublic int getCount()
返回当前已循环迭代的次数public java.lang.Object getCurrent()
返回当前迭代到的元素对象public java.lang.Integer getEnd()
返回为标签设置的end属性的值,如果没有设置end属性则返回nullpublic int getIndex()
返回当前迭代的索引号public java.lang.Integer getStep()
返回为标签设置的step属性的值,如果没有设置step属性则返回nullpublic 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)的更多相关文章
- JSP基础与提高(一).md
JSP基础 JSP的由来 1.1. 为什么有JSP规范 Servlet技术产生以后,在使用过程中存在一个很大的问题,即为了表现页面的效果而需要输出大量的HTML标签,这些标签在Servlet中表现为一 ...
- 动态页面技术JSP/EL/JSTL
本节内容: jsp脚本和注释 jsp运行原理 jsp指令(3个) jsp内置/隐式对象(9个) jsp标签(动作) EL技术 JSTL技术 JavaEE的开发模式 动态页面技术:就是在html中嵌入j ...
- JSP, EL, JSTL的使用
JSP基础指令和语法 回顾 在Jsp页面: 只要是Java代码就会原封不动的输出, 如果是html代码,就会转义为 out.write("<html>\r\n") 这样 ...
- jsp基础之 jstl
JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能. JSTL支持通用的.结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签. 除了这些,它还提供 ...
- JavaEE之动态页面技术(JSP/EL/JSTL)
动态页面技术(JSP/EL/JSTL) JSP技术 jsp脚本和注释 jsp脚本: 1)<%java代码%> ----- 内部的java代码翻译到service方法的内部 2)<%= ...
- JavaWeb之JSP & EL & JSTL
JSP & EL & JSTL JSP Java Server Page 什么是JSP 从用户角度看,就是一个网页.从程序员角度看,就是一个Java类,它继承Servlet,所以可以说 ...
- JAVA企业级开发--jsp,el,jstl(14)
三. EL表达式语言 EL 全名为Expression Language.表达式语言.jsp2.0之后才引入的. EL主要作用:替代:<%= %> out.print(); 获取数 ...
- 学会怎样使用Jsp 内置标签、jstl标签库及自定义标签
学习jsp不得不学习jsp标签,一般来说,对于一个jsp开发者,可以理解为jsp页面中出现的java代码越少,对jsp的掌握就越好,而替换掉java代码的重要方式就是使用jsp标签. jsp标签的分 ...
- JSP表达式语言(EL)
JSP表达式语言(EL)使得访问存储在JavaBean中的数据变得非常简单.JSP EL既可以用来创建算术表达式也可以用来创建逻辑表达式.在JSP EL表达式内可以使用整数型.浮点型.字符串.常量 ...
随机推荐
- java IO之 字符流 (字符流 = 字节流 + 编码表) 装饰器模式
字符流 计算机并不区分二进制文件与文本文件.所有的文件都是以二进制形式来存储的,因此, 从本质上说,所有的文件都是二进制文件.所以字符流是建立在字节流之上的,它能够提供字符 层次的编码和解码.列如,在 ...
- C#.NET 中visual studio生成的.pdb/ .vshost.exe/ .vshost.exe.manifest文件是什么
pdb文件: 英文全称:Program Database File 中文全称:程序数据库 文件 Debug里的PDB是full,保存着调试和项目状态信息.有断言.堆栈检查等代码.可以对程序的调试配 ...
- Spark笔记——技术点汇总
目录 概况 手工搭建集群 引言 安装Scala 配置文件 启动与测试 应用部署 部署架构 应用程序部署 核心原理 RDD概念 RDD核心组成 RDD依赖关系 DAG图 RDD故障恢复机制 Standa ...
- maven简介及基础使用
一.Maven简介 Maven可译为"知识的积累"."专家",主要服务于基于Java平台的项目构建.依赖管理和项目信息管理. 1.Maven-项目构建工具 ...
- 关于移动端自动化测试-Appium的搭建
web端我们常用的开源自动化用的是selenium,而移动端我们选择的是Appium,当然也可以使用monkey或者阿里的macaca,他们在理论上都使用了webdriver: 关于Appium环境的 ...
- javac.exe、 java.exe、 java虚拟机三者之间的区别与联系
JDK中 javac:Java编译器,将Java源代码换成字节代: java:Java解释器,直接从类文件执行Java应用程序代码: 先编译 *.java文件――――>*.class文件 运行 ...
- .Net 内存池
最近在开发 Pinpoint .Net 客户端,和服务端通信都是通过 TCP 或者 UDP,需要处理大量的 Byte 数据,使用 .Net Framework 只能通过 new Byte[] 的方式申 ...
- tar命令(转)
把常用的tar解压命令总结下,当作备忘: tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个, ...
- Linux常用命令和常见问题解决<------>第一章
查看文件下面所有的隐藏目录:ls -al ~ ls -al ~ls -a -l ~可以发现三条命令执行结果是一致的,原因:因为ls为命令 后面的参数要以空格来区分,不论几个空格 shell都会视为一体 ...
- Python简易爬虫爬取百度贴吧图片
通过python 来实现这样一个简单的爬虫功能,把我们想要的图片爬取到本地.(Python版本为3.6.0) 一.获取整个页面数据 def getHtml(url): page=urllib.requ ...