zoukankan      html  css  js  c++  java
  • JSTL和EL

    本章简介

    通过之前学习的三层架构,我们已经可以将表示层、业务逻辑层和数据访问层相互分离,从而实现程序的解耦合,以及提高系统的可维护性和可扩展性等。但在之前的代码中,表示层JSP的代码里仍然嵌套了很多JAVA代码,从而造成了表示层一定程度的混乱。

    能否彻底的从表示层中消除JAVA代码呢?可以使用 EL表达式和JSTL标签库。EL表达式和JSTL标签库不仅能替换JSP中的JAVA代码,而且还能使代码更加简洁。

    本章演示的项目名为ELAndJSTLDemo,因为本章只是在讲三层中的表示层,因此为了使读者清晰的掌握EL及JSTL,本章项目并没有采用标准的三层架构,而是以一个个简单的JSP示例来诠释。

    9.1 EL表达式

    EL的全称是Expression Language,可以用来替代JSP页面中的JAVA代码,从而能让即使不懂JAVA的开发人员也能写出JSP代码。EL还可以实现自动转换类型,使用起来非常简单。

    9.1.1 EL表达式语法

    语法:

    ${EL表达式}

    EL表达式通常由两部分组成:对象和属性。可以使用“点操作符”或“中括号[]操作符”来操作对象的属性。

    讲解之前,我们先通过一个简单例子来回忆一下之前不用EL的使用情景。先创建两个封装数据的JavaBean,如下,

    地址信息类 Address.java

    复制
    1. package org.lanqiao.entity;
    2. public class Address
    3. {
    4. //家庭地址
    5. private String homeAddress ;
    6. //学校地址
    7. private String schoolAddress ;
    8. //省略setter、getter
    9. }

    学生信息类 Student.java

    复制
    1. package org.lanqiao.entity;
    2. public class Student
    3. {
    4. private int studentNo ;
    5. private String studentName;
    6. //地址属性
    7. private Address address ;
    8. //省略setter、getter
    9. }

    再创建一个Servlet用于初始化一些数据,并将此Servlet设置为项目的默认访问程序:

    InitServlet.java

    复制
    1. package org.lanqiao.servlet;
    2. //省略import
    3. public class InitServlet extends HttpServlet
    4. {
    5. protected void doGet(…)…
    6. {
    7. this.doPost(request, response);
    8. }
    9. protected void doPost(HttpServletRequest request,
    10. HttpServletResponse response)
    11. throws ServletException, IOException
    12. {
    13. Address address = new Address();
    14. address.setHomeAddress("北京朝阳区");
    15. address.setSchoolAddress("北京大兴区大族企业广域网#6F2");
    16. Student student = new Student();
    17. student.setStudentNo(27);
    18. student.setStudentName("颜群");
    19. student.setAddress(address);
    20. request.setAttribute("student", student);
    21. request.getRequestDispatcher("index.jsp")
    22. .forward(request, response);
    23. }
    24. }

    web.xml

    复制
    1. <welcome-file-list>
    2. <welcome-file>InitServlet</welcome-file>
    3. </welcome-file-list>

    如上,程序会在InitServlet中给student对象的各个属性赋值,然后请求转发到index.jsp中。我们先用传统的Scriptlet接收对象,并将对象的属性显示到前台,如下,

    index.jsp

    复制
    1. <body>
    2. <%
    3. Student student = (Student)request.getAttribute("student");
    4. int studentNo = student.getStudentNo();
    5. String studentName = student.getStudentName();
    6. Address address = student.getAddress();
    7. String homeAddress = address.getHomeAddress();
    8. String schoolAddress = address.getSchoolAddress();
    9. out.print("学号:"+studentNo +"<br/>");
    10. out.print("姓名:"+studentName +"<br/>");
    11. out.print("家庭地址:"+homeAddress +"<br/>");
    12. out.print("学校地址:"+schoolAddress +"<br/>");
    13. %>
    14. </body>

    部署并执行此项目http://localhost:8888/ELAndJSTLDemo/,运行结果如图,

    图9-01

    可以发现,程序的确能够正常的显示。但如果将index.jsp中的代码用EL表达式来实现,就会简单许多。如下是使用EL修改后的index.jsp,功能与之前的Scriptlet代码相同,

    复制
    1. <body>
    2. <%-- 使用EL表达式 --%>
    3. 学生对象:${requestScope.student}<br/>
    4. 学号:${requestScope.student.studentNo } <br/>
    5. 姓名:${requestScope.student.studentName } <br/>
    6. 家庭地址:${requestScope.student.address.homeAddress } <br/>
    7. 学校地址:${requestScope.student.address.schoolAddress } <br/>
    8. </body>

    运行http://localhost:8080/ELAndJSTLDemo/,结果如图,

    图9-02

    综上,使用EL可以将JSP中的JAVA代码彻底消除,并且不用再做强制的类型转换,整体的JSP代码就会简单很多。

    9.1.2 EL表达式操作符

    (1)点操作符

    ${requestScope.student},表示在request作用域内查找student对象;${requestScope.student.studentNo },表示在request作用域内查找student对象的studentNo属性。点操作符“.”的用法和在JAVA中的用法相同,都是直接用来调用对象的属性。此外,通过${requestScope.student.address.homeAddress }可以发现,EL表达式能够级联获取对象的属性,即先在request作用域内找到student对象后,可以再次使用点操作符“.”来获取student内部的address对象……

    (2)中括号[]操作符

    除了点操作符以外,还可以使用中括号操作符来访问某个对象的属性,例如${requestScope.student.studentNo }可以等价写成${requestScope.student["studentNo"] }${requestScope["student"]["studentNo"] }。除此之外,中括号[]操作符还有一些其他独有功能:

    <1>如果属性名称中包含一些特殊字符,如“.”、“?”、“-”等,就必须使用中括号操作符,而不能用点操作符。例如,如果在之前的InitServlet中写了request.setAttribute("school-name", "LanQiao");那么在index.jsp中就不能用${requestScope. school-name },而必须改为${requestScope ["school-name "] }。

    <2>如果要动态取值时,也必须使用中括号操作符,而不能用点操作符。例如,String data=”school(即data是一个变量),那么就只能用${ requestScope [data]}。需要注意中括号里面的值:如果加了双引号则表示一个常量,如${requestScope ["school-name "] },表示获取"school-name "的属性值;而如果不加上双引号,则表示一个变量,如${ requestScope [data]},表示获取data所表示的school的属性值,即等价于${ requestScope [”school”]}。所以在使用中括号获取属性值时,一定要注意是否加引号。此外,中括号中的值,除了双引号以外,也可以使用单引号,作用是一样的。

    <3>访问数组。如果要访问request作用域内的一个对象名为names的数组,就可以通过中括号来表示索引,如${requestScope .array[0]}${ requestScope .array[1]}等。

    点操作符和中括号操作符还可以用来获取Map中的属性值,如下,

    InitServlet.java

    复制
    1. package org.lanqiao.servlet;
    2. //省略import
    3. public class InitServlet extends HttpServlet
    4. {
    5. protected void doPost(HttpServletRequest request,
    6. HttpServletResponse response)
    7. throws ServletException, IOException
    8. {
    9. Map<String,String> countries = new HashMap<String,String>();
    10. countries.put("cn", "中国");
    11. countries.put("us", "美国");
    12. request.setAttribute("countries", countries);
    13. request.getRequestDispatcher("index.jsp")
    14. .forward(request, response);
    15. }
    16. }

    index.jsp

    复制
    1. <body>
    2. ------------------Map------------------<br/>
    3. cn:${requestScope.countries.cn }<br/>
    4. us:${requestScope.countries["us"] }<br/>
    5. </body>

    打开浏览器执行http://localhost:8080/ELAndJSTLDemo/,运行结果如图,

    图9-03

    (3)关系运算符

    EL表达式还能够进行一些简单的运算。

      关系运算符 示例 结果
    大于 >(或gt) ${2>1}或${2 gt 1} true
    大于或等于 >=(或ge) ${2>=1}或${2 ge 1} true
    等于 ==(或eq) ${2==1}或${2 eq 1} false
    小于或等于 <=(或le) ${2<=1}或${2 le 1} false
    小于 <(或lt) ${2<1}或${2 lt 1} false
    不等于 !=(或ne) ${2!=1}或${2 ne 1} true

    (4)逻辑运算符

      关系运算符 示例 结果
    逻辑或 ||(或or) true||false(或 true or false) true
    逻辑与 &&(或and) true&&false(或 true and false) false
    逻辑非 !(或not) !true (或 not true) false

    (5)Empty操作符

    Empty操作符用来判断一个值是否为null或不存在。我们在InitServlet中给request的作用域内增加两个变量,如下,

    InitServlet.java

    复制
    1. package org.lanqiao.servlet;
    2. //省略import
    3. public class InitServlet extends HttpServlet
    4. {
    5. protected void doPost(HttpServletRequest request,
    6. HttpServletResponse response)
    7. throws ServletException, IOException
    8. {
    9. request.setAttribute("test","test");
    10. request.setAttribute("nullVar",null);
    11. request.getRequestDispatcher("index.jsp")
    12. .forward(request, response);
    13. }
    14. }

    request作用域内增加了testnullVar两个变量,并且nullVar的值是null。然后再在index.jsp中获取,如下,

    index.jsp

    复制
    1. <body>
    2. <%-- Empty操作符 --%>
    3. 之前不存在temp变量:${empty temp }<br/>
    4. 变量nullVar的值为null:${empty nullVar }<br/>
    5. 变量test已被赋值:${empty test }<br/>
    6. </body>

    运行结果:

    图9-04

    可以发现,之前不存在的变量temp和值为null的变量nullVar,用empty操作符运算出的结果为true,而之前存在值的变量testempty运算的结果为false。

    9.1.3 EL表达式隐式对象

    “隐式对象”又称“内置对象”。我们之前在JSP里曾提到过,像requestsessionapplication等都是JSP的隐式对象,这些“隐式对象”可以不用实例化就直接使用。同样的,在EL表达式中也存在一些隐式对象。按照使用的途径不同,EL隐式对象分为了作用域访问对象、参数访问对象和JSP隐式对象,如图,

    图9-05

    (1)四个作用域访问对象

    ${requestScope.student.studentNo }中的requestScope表示request作用域。即在使用EL表达式来获取一个变量的同时,可以指定该变量的作用域。EL表达式为我们提供了四个可选的作用域对象,如下表,

    对象名 作用域
    pageScope 把pageContext作用域中的数据映射为一个Map类的对象
    requestScope 把request作用域中的数据映射为一个Map类的对象
    sessionScope 把session作用域中的数据映射为一个Map类的对象
    applicationScope 把application作用域中的数据映射为一个Map类的对象

    pageScope, requestScope, sessionScope和appliationScope都可以看作是Map型变量,要获取其中的数据就可以使用点操作符或中括号操作符。如${requestScope.student}可以获取request作用域中的student属性值,${sessionScope[“user”]}可以获取session作用域中的user属性值。另外,如果不指定作用域,EL表达式就会依次从pageContextrequestsessionapplication的范围内寻找。例如,EL表达式在解析${student}时,就会先在pageContext作用域中查找是否有student属性,如果有则直接获取,如果没有则再会去request作用域中查找是否有student属性……

    (2)参数访问对象

    在JSP中,可以使用request.getParameter()request.getParameterValues()来获取表单中的值(或地址栏、超链接中附带的值)。对应的,EL表达式可以通过paramparamValues来获取这些值。

    对象名 示例 作用
    param ${param.usename} 等价于request.getParameter("username")
    paramValues ${param.hobbies} 等价于request. getParameterValues ("hobbies")

    (3)JSP隐式对象

    pageContext是JSP的一个隐式对象,同时也是EL表达式的隐式对象。因此,pageContext是EL表达式与JSP之间的一个桥梁。

    在EL表达式中,可以通过pageContext来获取JSP的内置对象和ServletContext对象,如下表:

    El表达式 获取的对象
    ${pageContext.page} 获取page对象
    ${pageContext.request} 获取request对象
    ${pageContext.response} 获取response对象
    ${pageContext.session} 获取session对象
    ${pageContext.out} 获取out对象
    ${pageContext.exception} 获取exception对象
    ${pageContext.servletContext} 获取servletContext对象

    还可以获取这些对象的getXxx()方法:例如,${pageContext.request.serverPort}就表示访问request对象的getServerPort()方法。可以发现,在使用时EL去掉了方法中的get和“()”,并将首字母改为了小写。

    小结:

    语法: ${EL表达式}

    其中${ }中的“EL表达式”可以是四个作用域访问对象、参数访问对象或JSP隐式对象pageContext三者之一。并且EL表达式可以像HTML一样直接写在JSP页面中,而不用被“<%… %>”括起来。

    9.2 JSTL标签及核心标签库

    JSTL(JSP Standard Tag Library,JSP标准标签库),是一个不断完善的开源JSP标签库,包含了开发JSP时经常用到的一组标准标签。使用JSTL,可以像EL表达式那样不用编写JAVA代码就能开发出复杂的JSP页面。JSTL一般要结合EL表达式一起使用。

    9.2.1 JSTL使用前准备

    使用JSTL标签库以前,必须先在Web项目的lib目录中加入两个jar包:jstl.jar和standard.jar,然后再在需要使用JSTL的JSP页面,加入支持JSTL的taglib指令,如下,

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

    其中prefix=”c”表示在当前页面中,JSTL标签库是通过标签使用的。

    9.2.2 JSTL核心标签库

    JSTL核心标签库主要包含三类:通用标签库、条件标签库和迭代标签库,如图,

    图9-06

    (1)通用标签库

    通用标签库包含了3个标签:赋值标签<c:set>、显示标签<c:out>、删除标签<c:remove>

    ①赋值标签<c:set>

    <c:set>标签的作用,是给变量在某个作用域内赋值,有两个版本:var版和target版。

    <1>var版

    用于给pagerequestsessionapplication作用域内的变量赋值

    语法:

    <c:set var="elementVar" value=" elementValue" scope="scope" />

    var:需要赋值的变量名

    value:被赋予的变量值

    scope:此变量的作用域,有4个可填项,即pagerequestsessionapplication

    示例:

    <c:set var="addError" value="error" scope="request"/>

    表示在request作用域内,设置一个addError变量,并将变量值赋值为error,等价于

    request.setAttribute("addError", "error");

    <2> target版

    用于给JavaBean对象的属性或Map对象赋值。

    a.给JavaBean对象的属性赋值

    语法:

    复制
    1. <c:set target="objectName" property="propertyName"
    2. value="propertyValue" scope="scope"/>

    target:需要操作的JavaBean对象,通常使用EL表达式来表示。

    property:对象的属性名。

    value:对象的属性值。

    scope:此属性值的作用域,有4个可填项,即pagerequestsessionapplication

    示例: 先通过Servlet给JavaBean对象的属性赋值,

    InitJSTLDataServlet.java

    复制
    1. package org.lanqiao.servlet;
    2. //省略import
    3. public class InitJSTLDataServlet extends HttpServlet
    4. {
    5. protected void doPost(HttpServletRequest request,
    6. HttpServletResponse response)
    7. throws ServletException, IOException
    8. {
    9. //将一个Address对象赋值后,加入request作用域,并请求转发到Jsp
    10. Address address = new Address();
    11. address.setHomeAddress("北京朝阳区");
    12. address.setSchoolAddress("北京大兴区大族企业广域网#6F2");
    13. request.setAttribute("address", address);
    14. request.getRequestDispatcher("JSTLDemo.jsp")
    15. .forward(request, response);
    16. }
    17. }

    JSTLDemo.jsp

    复制
    1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    2. <body>
    3. 使用JSTL赋值之前:${requestScope.address.schoolAddress }
    4. <br/>
    5. <c:set target="${requestScope.address }"
    6. property="schoolAddress" value="广东东莞蓝桥基地" />
    7. <br/>
    8. 使用JSTL赋值之后:${requestScope.address.schoolAddress }
    9. </body>

    运行InitJSTLDataServlet,结果如图,

    图9-07

    b.给Map对象赋值

    语法:

    复制
    1. <c:set target="mapName" property="mapKey"
    2. value="mapValue" scope="scope"/>

    target:需要操作的Map对象,通常使用EL表达式来表示。

    property:表示Map对象的key

    value:表示Map对象的value

    scope:此Map对象的作用域,有4个可填项,即pagerequestsessionapplication

    示例: 先通过Servlet给Map对象的属性赋值,如下

    InitJSTLDataServlet.java

    复制
    1. package org.lanqiao.servlet;
    2. //省略import
    3. public class InitJSTLDataServlet extends HttpServlet
    4. {
    5. protected void doPost(HttpServletRequest request,
    6. HttpServletResponse response)
    7. throws ServletException, IOException
    8. {
    9. //将一个Map对象赋值后,加入request作用域,并请求转发到JSTLDemo.jsp
    10. Map<String,String> countries = new HashMap<String,String>();
    11. countries.put("cn", "中国");
    12. countries.put("us", "美国");
    13. request.setAttribute("countries", countries);
    14. request.getRequestDispatcher("JSTLDemo.jsp")
    15. .forward(request, response);
    16. }
    17. }

    再使用<c:set/>Map对象的属性赋值,如下,

    JSTLDemo.jsp

    复制
    1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    2. <body>
    3. 使用JSTL赋值之前:${requestScope.countries.cn }、
    4. ${requestScope.countries.us }
    5. <br/>
    6. <c:set target="${requestScope.countries }" property="cn"
    7. value="中国人民共和国" />
    8. <br/>
    9. 使用JSTL赋值之后:${requestScope.countries.cn }、
    10. ${requestScope.countries.us }<br/>
    11. <br/>
    12. </body>

    运行InitJSTLDataServlet,结果如图,

    图9-08

    需要注意的是,<c:set>标签不仅能对已有变量赋值;如果需要赋值的变量并不存在, <c:set>也会自动产生该对象,如下,

    index.jsp

    复制
    1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    2. <body>
    3. 在request作用域内,并不存在temp变量:${requestScope.temp } <br/>
    4. 使用c:set直接给temp赋值为LanQiao
    5. <c:set var="temp" value="LanQiao" scope="request"/> <br/>
    6. 再次观察temp变量:${requestScope.temp } <br/>
    7. </body>

    运行结果:

    图9-09

    ②输出标签<c:out>

    输出标签<c:out>类似于JSP中的<%= %>,但功能更加强大。

    语法:

    <c:out value="value" default="defaultValue" escapeXml="isEscape"/>

    value:输出显示结果,可以使用EL表达式。

    default:可选项。当value表示的对象不存在或为空时,默认的输出值。

    escapeXml:可选项,值为true或false。为true时(默认情况),将value中的值以字符串的形式原封不动的显示出来;为false时,会将内容以HTML渲染后的结果显示。

    示例:

    先在InitJSTLDataServlet中创建address对象,然后给address中的schoolAddress属性赋值,再把address对象放入request作用域,之后请求转发到index.jsp,如下,

    InitJSTLDataServlet.java

    复制
    1. protected void doPost(HttpServletRequest request,
    2. HttpServletResponse response)
    3. throws ServletException, IOException
    4. {
    5. Address address = new Address();
    6. address.setSchoolAddress("北京大兴区大族企业广域网#6F2");
    7. request.setAttribute("address", address);
    8. request.getRequestDispatcher("JSTLDemo.jsp")
    9. .forward(request, response);
    10. }

    index.jsp

    复制
    1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    2. <body>
    3. request作用域中,存放了address对象及schoolAddress属性值:
    4. <c:out value="${requestScope.address.schoolAddress}" />
    5. <br/>
    6. request作用域中,不存在student对象:
    7. <c:out value="${requestScope.student}"
    8. default="student对象为空"/>
    9. <br/>
    10. 当escapeXml="true"时:
    11. <c:out value="<a href='https://www.baidu.com/'>百度主页</a>"
    12. escapeXml="true"/><br/>
    13. 当escapeXml="false"时:
    14. <c:out value="<a href='https://www.baidu.com/'>百度主页</a>"
    15. escapeXml="false"/>
    16. </body>

    执行InitJSTLDataServlet,运行结果:

    图9-10

    从结果可以发现,当value中输出的对象不存在或为空,会输出default指定的默认值;当escapeXml为false时,会将value中的内容先渲染成HTML样式再输出显示。

    ③移除标签<c:remove>

    <c:set>标签的作用,是给变量在某个作用域内赋值。与之相反,<c:remove>标签的作用,是移除某个作用域内的变量。

    语法:

    <c:remove var="variableName" scope="scope"/>

    var:等待被移除的变量名

    scope:变量被移除的作用域,有4个可填项:pagerequestsessionapplication

    示例:

    index.jsp

    复制
    1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    2. <body>
    3. 并不存在的一个变量varDemo:
    4. <c:out value="${varDemo }" default="不存在"/><br/>
    5. 在request作用域内,给varDemo赋值 为LanQiao
    6. <c:set var="varDemo" value="LanQiao" scope="request"/><br/>
    7. 再次观察varDemo:
    8. <c:out value="${varDemo }" default="不存在"/><br/>
    9. 在request作用域内,将varDemo移除:
    10. <c:remove var="varDemo" scope="request"/> <br/>
    11. 再次观察varDemo:
    12. <c:out value="${varDemo }" default="不存在"/><br/></body>

    运行结果:

    图9-11

    (2)条件标签库

    JSTL的条件标签库,包含单重选择标签<c:if>和多重选择标签<c:choose><c:when>、 <c:otherwise>

    ①单重选择标签<c:if>

    类似于Java中的if选择语句。

    语法:

    复制
    1. <c:if test="condition" var="variableName" scope="scope">
    2. 代码块
    3. </c:if>

    test:判断条件,值为truefalse,通常用EL表达式表示。当值为true时才会执行代码块中的内容。

    var:可选项。保存test的判断结果(true或false)。

    scope:可选项。设置此变量的作用域,有4个可填项:pagerequestsessionapplication

    示例:

    JSTLDemo02.jsp

    复制
    1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    2. <body>
    3. <c:if test="${3>2 }" var="result" scope="request">
    4. 3>2结果是:${result }
    5. </c:if>
    6. </body>

    运行结果:

    图9-12

    ②多重选择标签<c:choose>

    <c:choose>的功能类似于Java中的多重if。

    语法:

    复制
    1. <c:choose>
    2. <c:when test="">
    3. 代码块1
    4. </c:when>
    5. <c:when test="">
    6. 代码块2
    7. </c:when>
    8. ...
    9. <c:otherwise>
    10. 代码块n
    11. </c:otherwise>
    12. </c:choose>

    其中,<c:when test="">类似于Java中的判断语句:if()else if()<c:otherwise>类似于多重if中最后的else。具体的流程是:当<c:when>中的test为true时,执行当前<c:when>标签中的代码块;如果所有when中的test都为false,则才会执行<c:otherwise>中的代码块。

    示例:

    JSTLDemo02.jsp

    复制
    1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    2. <body>
    3. <c:set var="role" value="学生" />
    4. <c:choose>
    5. <c:when test="${role eq '老师' }">
    6. 老师相关代码
    7. </c:when>
    8. <c:when test="${role eq '学生' }">
    9. 学生相关代码
    10. </c:when>
    11. <c:otherwise>
    12. 管理员相关代码
    13. </c:otherwise>
    14. </c:choose>
    15. </body>

    运行结果:

    图9-13

    (3)迭代<c:forEach>标签库

    在Java之中有两种for循环,一种是传统的for循环,形式如for(int i=0;i<10;i++);另一种是增强的for循环,形式如for(String name : names) ,此处的names是字符串数组。类似的,在JSTL中也提供了两种<c:forEach>标签与之相对应,一种用于遍历集合对象的成员,另一种用于让代码重复的循环执行。

    ①遍历集合对象的成员

    语法:

    复制
    1. <c:forEach var="variableName" items="collectionName"
    2. varStatus="variableStatusInfo" begin="beginIndex"
    3. end="endIndex" step="step">
    4. 迭代集合对象的相关代码
    5. </c:forEach>

    var:当前对象的引用,即表示循环正在遍历的那个对象。例如,当循环遍历到第一个成员时,var 就代表第一个成员;当循环遍历到第二个成员时,var 就代表第二个成员……

    items:当前循环的集合名。

    varStatus:可选项。存放var所引用成员的相关信息,如索引号(index)等。

    begin:可选项。遍历集合的开始位置,从0开始。

    end:可选项。遍历集合的结束位置。

    step:可选项,默认为1。遍历集合的步长,比如当step为1时,会依次遍历第0个、第1个、第2个……;当step为2时,会依次遍历第0个、第2个、第4个……。

    示例: 先通过Servlet给集合中加入数据,再用<c:forEach>遍历输出。

    InitJSTLForeachDataServlet.java

    复制
    1. package org.lanqiao.servlet;
    2. //省略import
    3. public class InitJSTLForeachDataServlet extends HttpServlet {
    4. protected void doPost(HttpServletRequest request,
    5. HttpServletResponse response)
    6. throws ServletException, IOException {
    7. //Address类包含家庭地址和学校地址两个属性
    8. Address add1 =new Address("北京朝阳区","北京大兴区");
    9. Address add2 =new Address("陕西西安","广州东莞");
    10. List<Address> addresses = new ArrayList<Address>();
    11. addresses.add(add1);
    12. addresses.add(add2);
    13. //强addresses集合放入request作用域内
    14. request.setAttribute("addresses", addresses);
    15. request.getRequestDispatcher("JSTLDemo02.jsp")
    16. .forward(request, response);
    17. }
    18. }

    JSTLDemo02.jsp

    复制
    1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    2. <body>
    3. <c:forEach var="add" items="${addresses }" varStatus="status" >
    4. ${status.index}:
    5. 家庭地址:${add.homeAddress } –
    6. 学校地址:${add.schoolAddress }<br/>
    7. </c:forEach>
    8. </body>

    执行http://localhost:8888/ELAndJSTLDemo/InitJSTLForeachDataServlet,运行结果:

    图9-14

    ②迭代指定的次数

    语法:

    复制
    1. <c:forEach var="variableName" varStatus="variableStatusInfo"
    2. begin="beginIndex" end="endIndex" step="step">
    3. 循环体
    4. </c:forEach>

    其中varvarStatusbeginendstep属性的含义,与“遍历集合对象的成员”中对应的属性含义相同,并且能发现此种方式的<c:forEach>缺少了items属性。此种方式的<c:forEach>主要用来让循环体执行固定的次数。

    示例:

    JSTLDemo02.jsp

    复制
    1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    2. <body>
    3. <c:forEach begin="0" end="2" step="1">
    4. LanQiao<br>
    5. </c:forEach>
    6. </body>

    以上代码中的<c:forEach>类似于Java中的for(int i=0;i<2;i++),运行结果:

    图9-15

    至此我们就学完了EL表达式和JSTL标签库的相关内容,读者可以使用它们来替换以前JSP页面中的Scriptlet。

    9.3 练习题

    一、选择题

    1.下面( )不是与范围有关的EL隐式对象。(选择一项)(难度★)

    A.cookieScope

    B.pageScope

    C.sessionScope

    D.applicationScope

    2.如果session中已经有属性名为user的对象,则EL表达式${not empty sessionScope.user}的值为( )。(选择一项)(难度★)

    A.true

    B.false

    C.null

    D.user

    二、简答题

    1.在使用EL表达式时,如果不显式指定对象的作用域范围,则系统会按照什么顺序依次查找?(难度★)

    2.使用JSTL标签<c: ... >之前,需要进行哪些准备工作?(难度★)

    3.请问<c:set>标签有哪几种?各如何使用?(难度★★)

    4.请介绍JSTL中的for Each迭代标签有哪些属性,并简要描述各属性的含义。(难度★★★)

    5.使用EL和JSTL继续优化第七章练习题中的“部门管理系统”。(难度★★★)

  • 相关阅读:
    HDFS源码分析(六)-----租约
    YARN源码分析(一)-----ApplicationMaster
    YARN源码分析(一)-----ApplicationMaster
    YARN源码分析(一)-----ApplicationMaster
    YARN源码分析(二)-----ResourceManager中的NM节点管理
    YARN源码分析(二)-----ResourceManager中的NM节点管理
    Confluence 6 如何备份和恢复
    Confluence 6 那些文件需要备份
    Confluence 6 确定一个生产系统备份方案
    Confluence 6 生产环境备份策略
  • 原文地址:https://www.cnblogs.com/gu-bin/p/10547363.html
Copyright © 2011-2022 走看看