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”结构的条件表达式,如果条件表达式的结果为真就执行标签体部分的内容。标签有两种语法格式:
   
- 语法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,如果指定了标签的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:otherwise>标签一起使用。使用<c:choose>,<c:when>和三个标签,可以构造类似 “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>标签,就相当于“i**f-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)。对字符串的迭代操作通常使用标签或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 参数的值

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

时间: 2024-09-11 13:47:31

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

JSP基础与提高(一)

JSP基础 JSP的由来 1.1. 为什么有JSP规范 Servlet技术产生以后,在使用过程中存在一个很大的问题,即为了表现页面的效果而需要输出大量的HTML标签,这些标签在Servlet中表现为一个个的字符串常量.这种输出页面的方式不仅仅增加了开发时对页面的控制难度,也不利于后期的维护. 为了能够将Servlet中用于表现的功能分离出来,提高视图的开发效率,推出了JSP这种技术,主要用于将Servlet中负责显示的语句抽取出来. 1.2. 什么是JSP JSP(Java Server Pag

servlet-Servlet中跳转至jsp中如何通过EL表达式取出对象的值

问题描述 Servlet中跳转至jsp中如何通过EL表达式取出对象的值 解决方案 直接这样就可以了:${user.name}假设user对象有一个name属性是你需要的. 解决方案二: 还可以用user.getXxx(),取实体类里面的值 解决方案三: ${user.name},然后在显示层取出它就行了 例如user.setName(model.getName()),这样就可将他持久化到数据库中了; 解决方案四: el表达式${user.xxx}就可以,如果是list或者集合类型,可以用jstl

SpringMVC的JSP页面中中EL表达式不起作用的问题解决

今天,我在写SpringMVC代码的时候遇到了一个问题,就是在jsp页面中使用el表达式取值,取不到值,但是使用jsp中嵌套java代码可以取到值. 问题如下图: 起初,我以为是jstl标签没有导入,但是经过检查,并不是这个原因,害我试了好久,还是没改出来.后来上网谷歌搜索一下才发现了问题所在! 解决方法: 在使用el表达式的jsp中配置: <%@page isELIgnored="false" %> 更改后就显示正确,如下: 该设置代表在本jsp中使用el表达式,可以解析

jsp基础语法 一 scriptlet

jsp作为WEB的开发基础,有其重要的地位,那么熟练掌握JSP的语法及应用就成了重中之重. 首先我们一起先从JSP的基本语法学起:(以下内容来自李兴华视频手稿整理) scriptlet简介 script表示的是脚本小程序,像之前out.println()这个语句是缩写在<%%>之中的,很明显,这里面 缩写的语句就是一个script. 在jsp中最重要的部分就是Scriptlet(脚本小程序),所有嵌入在HTML代码中的java程序都必须使用 Scriplet标记出来,在jsp中一共有三种scr

jsp基础语法 六 jsp+jdbc访问数据库

学习过了jsp基础语法以及HTML和javascript的用法之后,jsp+jdbc连接数据库开发动态WEB网页就可以实现了. 对于学过java SE的同学来说,数据库的操作并不陌生,如果有忘记的或者不会的可以到http://zhaoyuqiang.blog.51cto.com/6328846/1127658  学习. jsp中的数据库连接又是如何呢? 怎样才能利用上我们学过的HTML和javascript的知识呢? 这就是我们这一篇文章的学习内容----jsp+jdbc访问数据库. 我们就以一

jsp基础语法 五 跳转指令

跳转的作用: 使用跳转指令可以将一个用户的请求,从一个页面传递到另外一个页面. 例如:用户登录QQ空间,如果用户名和密码正确的话就会跳转到空间首页,否则就会跳转到失败页. 跳转指令的语法: 不传递参数   <jsp:forward page=""/> 传递参数:  <jsp:forward page=""> <jsp:param name="参数名称" value="参数内容"> </

jsp基础语法 四 包含指令

什么是包含: 在页面开发的时候,一些代码难免会有重复使用的情况,比如说A页面有一段代码a,B页面和C页面都能用到a这段代码,那么B和C页面就把A页面包含进来,自然的a这段代码也被包含进BC页面了,这样就实现了B.C页面能用到a代码了,避免了重复的书写a代码. 包含的意义: 使用包含操作,可以将一些重复的代码包含进来继续使用. 一般分为如上四个区域. 真正在改变的地方只是具体内容,因为根据不同的用户浏览的不同,那么肯定这上面会存在差别  现在就有两种做法实现以上一种功能 方法一:在没有一个jsp页

jsp基础语法 三 page指令

page指令 page指令是在jsp开发中较为重要,使用此属性,可以定义一个jsp页面的相关属性,包括 设置MIME类型.定义需要导入的包.错误页的指定等 page指令的语法:<%@ page 属性="内容"%> page的主要属性: 设置MIME 先来观察一道程序: <html> <head> <title> New Document </title> </head> <body> <cente

jsp基础语法 二 注释的使用

我的一个同学问我,java中有"//"这个样的注释,用起来挺方便的,jsp的注释难道不是这个吗?用"//"在jsp中不行. 对于学习了这么长时间的jsp,注释是最基本的.jsp中的注释不同于java. 在jsp中支持两种注释,一种是显示注释,这种注释客户端是允许看见的,另外一种注释是隐式注释,此种注释客户端是无法看见的. 显示注释语法: <!--注释内容--> 隐式注释语法: 格式一:// 注释,单行注释: 格式二:  /* 注释 */,多行注释: 格式