1 EL表达式
1.1概念
EL(Expression 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个作用域中取出数据。
语法: ${expression} expression可以是表达式,也可以是作用域中的属性的名称。
案例:
在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="yyyy年MM月dd日 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> |