EL&JSTL

本文深入讲解了EL表达式和JSTL的核心概念,包括EL如何简化JSP页面数据获取,JSTL如何增强页面逻辑处理能力,以及两者如何结合使用优化页面表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1 EL表达式

1.1概念

ELExpression Language 是为了使JSP写起来更加简单。表达式语言的灵感来自于 ECMAScript XPath 表达式语言,它提供了在 JSP 中简化表达式的方法,让Jsp的代码更加简化。

4个作用域中获取数据.

 

1.2从4个作用域中获取数据

         回顾4个作用域

         Application > session >request >page

Application  session  request  pageContext

 

通过4个对象可以使用setAttribute(String attrName,Object attrValue)方法给作用域设置属性。通过getAttribute(String attrName) 从4个作用域中获取数据;

 

将servlet中查询的数据传递到页面:在servlet中获取数据,将数据设置到request作用域中。在JSP页面通过request对象取出。

EL表达式可以在不使用java脚本的情况下从4个作用域中取出数据。

 

语法:  ${expressionexpression可以是表达式,也可以是作用域中的属性的名称。

案例:

在servlet中向4个作用域中添加属性,在页面通过EL取出。

添加servlet

public class ElServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

       //分别向4个作用域中添加属性

       //pageContext对象无法在这里网页面的page作用域中添加属性。

       request.setAttribute("requestAttr", "这是request的属性值");

       HttpSession session = request.getSession();

       session.setAttribute("sessionAttr", "这是session的属性值");

       ServletContext application = this.getServletContext();

       application.setAttribute("applicationAttr", "这是applilcation的属性值");

       //转发进入el.jsp

       request.getRequestDispatcher("el.jsp").forward(request, response);

    }

 

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

       doGet(request, response);

    }

 

}

 

JSP页面:

<div>

    <%pageContext.setAttribute("pageAttr", "这是page作用域中的属性值"); %>

    <h2>取出4个作用域的数据</h2>

    <ul>

       <li>page:${pageScope.pageAttr }</li>

       <li>request:${requestScope.requestAttr }</li>

       <li>session:${sessionScope.sessionAttr }</li>

       <li>application:${applicationScope.applicationAttr }</li>

    </ul>

</div>

效果:

在上面的案例中,使用xxxxScope指定了获取属性值的作用域,其实xxxxScope是可以省略不写的,例如:

 

    <h3>省略scope</h3>

    <ul>

       <li>page:${pageAttr }</li>

       <li>request:${requestAttr }</li>

       <li>session:${sessionAttr }</li>

       <li>application:${applicationAttr }</li>

    </ul>

效果:

有一些特殊的不能省略的情况:

比如4个作用域中设置了相同属性名称的属性

       //添加相同的属性

       request.setAttribute("igeek", "requestIgeek");

       session.setAttribute("igeek", "sessionIgeek");

       application.setAttribute("igeek", "applicationIgeek");

获取方式:

    <h3>取出相同属性名的属性值</h3>

    <ul>

       <li>省略score的取值方式:${igeek }</li>

       <li>page的取值方式:${pageScope.igeek }</li>

       <li>request的取值方式:${requestScope.igeek }</li>

       <li>session的取值方式:${sessionScope.igeek }</li>

       <li>application的取值方式:${applicationScope.igeek }</li>

    </ul>

效果:

当指定作用域时,获取的就是指定的作用域的属性值。

当省略时,EL会默认从最小的作用域开始搜索 , 找到为止。

常规的业务中不会出现不同作用域中设置相同名称的属性。所以一般情况下我们都是省略scope。

 

如果el中要获取的数据不存在,就不显示。

    <h3>获取一个不存在或者为null的值</h3>

    <% pageContext.setAttribute("key", null); %>

    <ul>

       <li>不存在的值:${ndwl }</li>

       <li>null的值:${key }</li>

    </ul>

效果:

1.3EL表达式的禁用

在servlet2.0之前EL表达式是默认禁止的。

可以通过page指令中的属性:isELIgnored  设置EL表达式是否被忽略。

默认是false,如果设置为true。效果:

 

1.4通过EL表达式访问对象的属性

EL表达式可以通过”.”或者[“attrName”]访问对象的属性。

案例:

创建一个Computer类:

public class Computer {

    private String brand;

    private double price;

    private MainBoard board;

}

添加主板类:

public class MainBoard {

    private String brand;

    private int size;

}

在serlvet中创建主板对象放入request:

       //创建主板对象

       MainBoard board = new MainBoard("华硕", 56);

       request.setAttribute("board", board);

JSP中的获取

    <h3>获取一个对象的属性值</h3>

    <ul>

       <li>获取主板对象:${board }</li>

       <li>.获取主板的品牌:${board.brand }</li>

       <li>[]获取主板的品牌:${board["brand"] }</li>

    </ul>

效果:

1.5EL获取对象属性的实质

         JavaBean规范中,成员变量必须是私有的。

         EL可以通过.直接获取

       

看似直接获取的,其实也是通过反射机制调用其getXxx方法获取的。

修改brand中的getBrand的方法:

再访问:错误  无法访问私有属性brand

1.6EL访问属性可以多层导航

比如:

在servlet添加一个computer,在页面中访问电脑的主板的品牌。

Servlet

       //创建主板对象

       MainBoard board = new MainBoard("华硕", 56);

       request.setAttribute("board", board);

       //创建电脑对象

       Computer com = new Computer("联想", 8000);

       com.setBoard(board);

       request.setAttribute("com", com);

JSP

    <h3>获取一个对象的属性的属性</h3>

    <ul>

       <li>获取电脑对象:${com }</li>

       <li>获取电脑的主板:${com.board }</li>

       <li>获取电脑的主板的主板的品牌:${com.board.brand }</li>

    </ul>

效果:

 

1.7EL表达式中的运算符

回顾运算符:

算术运算符,关系运算符,逻辑运算符。

这些运算符在EL中同样适用。

    <h3>EL的运算符</h3>

    <ul>

       <li>算术运算符1:${1+1 }</li>

       <li>算术运算符2:${board.size+100 }</li>

       <li>关系运算符:${com.price > 6000 }</li>

       <li>逻辑运算符:${com.price>6000 && com.price < 10000 }

       <li>三目运算:${com==null?"没有电脑":com.brand }</li>

    </ul>

效果:

1.8在JS中使用EL表达式

由于el表达式使用$ 而在jquery中同样使用$,此时如果在js中使用el表达式就出现冲突。

EL表达式可以使用在页面的任何位置:比如:

效果:

但是如果导入了jquery,jquery的$就会和El的$冲突:

<script type="text/javascript">

    $(document).ready(function(){

       console.log("${com.price}");

    });

</script>

解决方案就是将el表达式使用””包裹

效果:浏览器中生成的代码

 

2 JSTL

2.1概述

JSTL(JavaServer Pages Standard Tag Library,JSP标准标签库)是一个不断完善的开放源代码的JSP标签库,是由apache的jakarta小组来维护的。JSTL只能运行在支持JSP1.2和Servlet2.3规范的容器上,如tomcat 4.x。在JSP 2.0中也是作为标准支持的。

JSTL 1.0 发布于 2002 年 6 月,由四个定制标记库(core、format、xml 和 sql)和一对通用标记库验证器(ScriptFreeTLV 和 PermittedTaglibsTLV)组成。core 标记库提供了定制操作,通过限制了作用域的变量管理数据,以及执行页面内容的迭代和条件操作。它还提供了用来生成和操作 URL 的标记。顾名思义,format 标记库定义了用来格式化数据(尤其是数字和日期)的操作。它还支持使用本地化资源束进行 JSP 页面的国际化。xml 库包含一些标记,这些标记用来操作通过 XML 表示的数据,而 sql 库定义了用来查询关系数据库的操作。

如果要使用JSTL,则必须将jstl.jar和 standard.jar文件放到classpath中,如果你还需要使用XML processing及Database access (SQL)标签,还要将相关JAR文件放到classpath中,这些JAR文件全部存在于下载回来的zip文件中。

         JSTL就是用来处理EL表达式取出的数据的。

2.2JSTL的安装

下载:http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/

下载后解压:

取出lib中的jar文件添加在自己项目的classpath中,所谓classpath中就是添加到WEB-INF/lib中

在网页中使用JSTL

关于uri和prefix属性

查看JSTLjar中的标签描述文件:

标签描述文件中定义了JSTL标签的相关的配置和使用方式。以及各种标签的申明:

其中的short-name就是此标签的默认前缀,当然在页面可以通过profix修改:

但不允许修改。

其中的uri属性相当于此标签的唯一标识符。在页面引用时需要在uri中申明。

2.3核心标签库中的c:set,c:out,c:remove

C:set  相当于 xxx.setAttribute();

    <c:set var="igeek" value="igeekhome" scope="page"/>

    ${igeek }

属性 var :属性的名称    value :属性值,可以使用el表达式

Score:是作用域。

C:out 相当于 <%= xx %>

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

属性value:要展示的数据,可以使用el表达式

C:remove 相当于xxx.removeAttribute();

<c:remove var="igeek"/>

属性var就要删除的作用域中的属性名称

 

2.4核心标签库中的if标签

语法:  <c:if test=”” var=””></if>

    <c:set var="igeek" value="80" >

    <c:if test="${igeek>70 }" var="result" scope="page"/>

       igeek属性是大于70

    </c:if>

当test属性的值为true就执行if标签内部的程序。

其中属性var是说创建一个变量result存储test比较的结果.

Scope属性是配置result变量存储的作用域。

效果:

 

2.5 c:choose,c:when,c:other wise

案例:

    <div>

       <c:set var="igeek" value="60"/>

       <c:choose>

           <c:when test="${igeek>70 }">

              igeek属性是大于70

           </c:when>

           <c:when test="${igeek>80 }">

              igeek属性是大于80

           </c:when>

           <c:otherwise>

              igeek是其他情况

           </c:otherwise>

       </c:choose>

    </div>

效果:

此标签类似于java中的

If  ..  else if .. else if ….else

2.6 c:foreach

用来循环的标签,类似于java中的for和foreach

使用foreac做循环

案例:

       <div>for 循环

           <ul>

           <c:forEach begin="1" end="11" step="2" var="i" varStatus="status" >

              <li>Item ${i }--${status.index }--${status.count }</li>

           </c:forEach>

           </ul>

       </div>

效果:

属性:

Begin: 循环的起始值。

End:循环的结束之。

Step:步长。

Var:定义一个变量i,把每次循环的变量存储在i中。

Varstatus:定义一个变量status,存储每次循环的状态。Status有循环的索引和循环的总数。

 

属性中定义的var和varstatus都是默认存储在page作用域中的属性。所以可以通过el表达式直接获取:

其中i就是循环的值,status.index就是循环的索引,status.count就是循环的总数量。

 

使用foreach遍历列表

       <div>使用foreach遍历列表</div>

       <%

           List<String> sts = new ArrayList<String>();

           sts.add("张三");sts.add("李四");sts.add("王五");

           sts.add("卡卡西");sts.add("鸣人");sts.add("佐助");

           pageContext.setAttribute("sts", sts);

       %>

       <c:forEach items="${sts }" var="s" varStatus="status">

           <p>${status.index }.${s }--${status.count }</p>

       </c:forEach>

效果:

Tips:items是设置要遍历的列表的,一般都是通过el表达式获取作用域中的集合。切记不能忘记$   items中{}以外不能有空格。

Foreach遍历数据类型:collection.  数组。

 

2.7 c:fortokens

用来分割循环的

案例:

    <h3>forTokens</h3>

    <div>

       <c:set var="igeek" value="igeek is a NB 的机构"/>

       <c:forTokens items="${igeek }" delims=" " var="s" varStatus="status">

           <p>${status.index }.${s }</p>

       </c:forTokens>

    </div>

效果:

2.8日期格式化标签

格式化标签在格式化标签库中

在页面引用格式化标签库:

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

格式化日期:

    <h3>fmt:formatDate</h3>

    <div>

       <c:set var="now" value="${date }"/>

       <ul>

           <li>不格式化:${now }</li>

           <li>格式化日期(type=date):<fmt:formatDate type="date" value="${now }"/></li>

           <li>格式化日期(type=time):<fmt:formatDate type="time" value="${now }"/></li>

           <li>格式化日期(type=BOTH):<fmt:formatDate type="BOTH" value="${now }"/></li>

           <li>格式化日期(timeStyle=short):<fmt:formatDate dateStyle="short" type="BOTH" timeStyle="short" value="${now }"/></li>

           <li>格式化日期(timeStyle=long):<fmt:formatDate dateStyle="long" type="BOTH" timeStyle="long" value="${now }"/></li>

           <li>自定义格式化(patten):<fmt:formatDate type="BOTH" pattern="yyyyMMdd HH:mm:ss" value="${now }"/></li>

       </ul>

    </div>

效果:

2.9日期解析标签

parseDate  用于将字符串形式的日期转换为date

 

    <h3>fmt:formatDate</h3>

    <div>

       <c:set var="now" value="2018-5-25 12:45:56"/>

       <fmt:parseDate var="n" value="${now }" pattern="yyyy-MM-dd HH:mm:ss"/>

       ${n }

    </div>

效果:

 

3.JSTL和EL表达式净化页面

将前面的BBS项目中的list页面进行净化

[1]添加jar文件

[2]在list.jsp中引用核心标签库和格式化标签库

[3]修改页面代码。判断数据是否存在:

<c:if test="${board==null }">

    <!-- 重定向到首页 -->

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

</c:if>

[4]修改页面。判断用户登录状态

<%--判断是否登录 --%>

                  <c:choose>

                     <c:when test="${loginUser ==null }">

                         [<a href="reg.jsp">注册</a>]

                         [<a href="login.jsp">登录</a>]

                     </c:when>

                     <c:otherwise>

                         欢迎您${loginUser.nickName }

                         <a class="btn btn-default" href="inputPost?boardId=${board.boardId }">快速发帖</a>

                     </c:otherwise>

                  </c:choose>

[5]修改页面。判断帖子数据是否存在

<c:if test="${topics==null }">

                     <tr>

                         <td colspan="3">

                            该板块暂时没有任何话题

                         </td>

                     </tr>

                  </c:if>

[6]修改页面。使用foreach遍历集合

<c:if test="${topics!=null }">

                     <c:forEach items="${topics }" var="t">

                         <tr>

                            <td>${t.topicId }</td>

                            <td>

                                <a href="detail?topicId=${t.topicId }">${t.title }</a>

                            </td>

                            <td>${t.createTime }</td>

                         </tr>

                     </c:forEach>

                  </c:if>

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值