<%for (House house : mockHouses) { System.out.println(house); %><li><h2><a href=\"大众house-details.jsp?userName=${param.userName}&houseId=<%=house.getId() %>\"大众><%=house.getName() %></a></h2></li><%} %>

像这样的代码我们可以利用JSTL技能来办理。
当然,JSTL可不仅仅只有这点功能,你还可以定义自己的标签。

在这篇文章里,我提到过JSTL是JSP干系的技能,从它的名字全称(JSP Standard Tag Library,即JSP标准标签库)就可以看出来。

在本篇文章里,我们就考试测验初步利用JSTL来进一步改造我们的租房网运用。

jsp取list长度Java Web轻松学41  JSTL初步应用 Angular

JSTL规范下载

既然称之为库,那么它包含哪些库呢?

我们可以把JSTL规范下载下来看一下,当然你也可以找本相关书本,或者直接在网上搜索一下。

JSTL规范的下载类似Servlet规范的下载(可以参考这篇文章),不过我们在JCP官网(https://jcp.org/en/home/index)中搜索的关键字就变成Tag或Tag Library了。

我们在搜索结果中就可以看到:

点击 Download page 链接可以看到:

然后连续点击底部的 Maintenance Review 2 of JSR 52 链接,跳转到:

不过,再次点击DOWNLOAD按钮时,我这边涌现无法访问此网站的缺点。
以是我转而点击底部的 JSR-000052 A Standard Tag Library for JavaServer Pages Detail Page 链接:

从这里我们可以看到JSTL规范的各个阶段,我们选择 Maintenance Release 2 这个阶段,点击它右边的 Download page 链接:

然后再点击赤色箭头所指的链接,跳转到真正的下载页面:

后续操作就跟Servlet规范的下载类似了。

JSTL包含哪些库

现在,我们可以打开JSTL规范,可以看到如下描述:

事实上,JSTL该当就只是一个库,但它根据不同功能而划分成了多个库:

核心:变量支持、流掌握、URL管理等等,它的命名空间URI是:http://java.sun.com/jsp/jstl/core,标签前缀常日利用:cXML处理:它的命名空间URI是:http://java.sun.com/jsp/jstl/xml,标签前缀常日利用:x国际化:措辞区域、格式化、数字和日期格式化等,它的命名空间URI是:http://java.sun.com/jsp/jstl/fmt,标签前缀常日利用:fmt数据库访问(SQL):它的命名空间URI是:http://java.sun.com/jsp/jstl/sql,标签前缀常日利用:sql函数:凑集长度、字符串操作等,它的命名空间URI是:http://java.sun.com/jsp/jstl/functions,标签前缀常日利用:fnJSTL如何利用

JSTL的终极目标是简化JSP页面的开拓,以是,它该当是在JSP页面中利用。

既然是标签,那它的利用是否跟HTML标签、XML标签类似呢?答案是肯定的。

不过,JSTL标签的利用与XML标签利用时声明命名空间类似,也须要见告Servlet/JSP容器该JSP页面须要引入某个库(即上述的核心、XML处理、国际化、数据库访问、函数等等,以及往后自定义的标签)。

在JSP页面中是利用一个JSP指令(即taglib指令,之前我们用过page指令)来声明的:

<%@ taglib uri=\公众uri\"大众 prefix=\"大众prefix\"大众 %>

举个例子,假设我们要利用JSTL的核心库,则该当在JSP页面的开头处这样声明:

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

然后,就可以利用核心库的标签,比如out标签:

<c:out value=\"大众value\"大众 [escapeXml=\"大众{true|false}\公众] [default=\"大众defaultValue\"大众]/><c:out value=\"大众value\"大众 [escapeXml=\"大众{true|false}\"大众]> default value</c:out>

把稳:在标签的语法中,[]表示可选的属性。
如果值带下划线,则表示为默认值。

out标签有两种形式,有属性和属性值,也可能有标签内容,跟HTML标签和XML标签类似。

租房网运用中利用JSTL

我们就拿租房网运用中的房源列表页面houses.jsp来利用JSTL改造,由于这里涉及列表数据的展示。

列表数据是很常见的,我们常常可以看到包含列表数据的页面,比如订单列表、商品列表等等。

houses.jsp原来的代码是这样的:

<%@ page language=\"大众java\"大众 contentType=\公众text/html; charset=UTF-8\"大众 pageEncoding=\公众UTF-8\公众%><%@ include file=\"大众include.jsp\公众%><%List<House> mockHouses = (List<House>) request.getAttribute(\"大众mockHouses\"大众);System.out.println(mockHouses);%><h6>共找到你感兴趣的房源 <%=mockHouses.size() %> 条</h6><ul><%for (House house : mockHouses) { System.out.println(house); %><li><h2><a href=\"大众house-details.jsp?userName=${param.userName}&houseId=<%=house.getId() %>\"大众><%=house.getName() %></a></h2></li><%} %></ul></body></html>

首先要引入JSTL中的核心库(由于我们后面要用到的forEach标签是属于核心库的):

<%@ page language=\"大众java\公众 contentType=\"大众text/html; charset=UTF-8\"大众 pageEncoding=\"大众UTF-8\"大众%><%@ include file=\"大众include.jsp\"大众%><%@ taglib uri=\"大众http://java.sun.com/jsp/jstl/core\"大众 prefix=\公众c\"大众 %>

遗憾的是,我们添加这句声明之后,Eclipse就报错了:

提示是说找不到这个标签库的描述符。
那就根据这个提示在网上搜索答案呗。

答案便是原来我们还须要在我们的工程构造里配置JSTL干系的JAR包,而Tomcat这个Servlet/JSP容器本身不供应这些JSTL干系的JAR包,我们须要单独下载。

JSTL干系的JAR包

那么在哪里下载呢?既然我们是利用Tomcat这个Servlet/JSP容器,那么我们就可以到它的官网(http://tomcat.apache.org/)上看看:

我们可以看到左侧导航栏中有个Taglibs链接,我们点进去看看:

还真便是JSTL干系JAR包的下载页面,点击Download链接进去,可以找到真正的下载链接:

我们可以看下Binary README文件,里面有该JAR包版本支持的Tomcat和JSP等版本信息,如果我们利用的Tomcat是最新版本(9.0.x),那直接下载下面四个JAR包即可,否则须要点进Archives页面下载历史版本。

好,我们把四个JAR包下载下来之后,就可以添加到我们的租房网运用的工程里面了,可以参考这篇文章。

实际上,直接把这四个JAR包拷贝到WebContent/WEB-INF/lib节点下是最快的。

现在,我们可以看到上述的Eclipse报错提示就消逝了。

EL表达式访问列表的长度

首先,我们可以利用EL表达式来访问列表的长度:

<h6>共找到你感兴趣的房源 ${mockHouses.size()} 条</h6>

听说低版本的JSP容器不可以这样直接用EL表达式来访问列表的长度,而该当利用JSTL的函数库中的length方法:

${fn:length(list) }

当然,首先须要引入JSTL的函数库。
读者朋友可以自行考试测验一下。

JSTL的forEach标签

我们可以通过JSTL规范查看一下这个forEach标签的用法:

当然,可能只看这个语法格式还是不太明白如何利用,那么可以连续看规范中的描述,或者直接网上搜索即可。

我们须要改造的代码是这一部分:

<%for (House house : mockHouses) { System.out.println(house); %><li><h2><a href=\"大众house-details.jsp?userName=${param.userName}&houseId=<%=house.getId() %>\公众><%=house.getName() %></a></h2></li><%} %>

我们可以先把它注释掉(在Eclipse中可以选中这一段,然后键入Ctrl + Shift + /),然后敲入开始标签的左尖括号 < ,于是Eclipse会涌现智能提示:

嗯,这个功能还是挺好用的,提高开拓效率。

闲话不多说了,直接上代码:

<c:forEach var=\"大众house\公众 items=\"大众${mockHouses}\"大众><li><h2><a href=\"大众house-details.jsp?userName=${param.userName}&houseId=${house.id}\公众>${house.name}</a></h2></li></c:forEach>

看似跟之前变革不大,但至少没那么奇葩了,风格也与HTML很同等。

forEach标签遍历列表数据的基本属性是:

var:相称于定义一个变量来表示指向列表中的某一项;items:指定须要遍历哪个列表,须要把稳的是其值又是利用EL表达式来访问页面/要求/会话/运用中的某个属性数据(即利用setAttribute()添加的工具)

forEach标签的内容就可以是普通的HTML标签了,然后HTML标签里我们就可以利用EL表达式来访问列表中每一项数据。

实际上,EL表达式直接访问工具的属性,而非调用工具的方法,比如:

${house.id}

把稳,param是EL的隐式工具,它是由Servlet/JSP容器创建并传进来的,它可以直接访问要求所携带的参数。

以是,我们实际上可以把原来的这一部分:

<%List<House> mockHouses = (List<House>) request.getAttribute(\公众mockHouses\"大众);System.out.println(mockHouses);%>

删除掉。

现在houses.jsp的代码就变成这样了:

<%@ page language=\"大众java\"大众 contentType=\"大众text/html; charset=UTF-8\"大众 pageEncoding=\"大众UTF-8\"大众%><%@ include file=\公众include.jsp\公众%><%@ taglib uri=\"大众http://java.sun.com/jsp/jstl/core\"大众 prefix=\"大众c\"大众 %><h6>共找到你感兴趣的房源 ${mockHouses.size()} 条</h6><ul><c:forEach var=\"大众house\"大众 items=\公众${mockHouses}\"大众><li><h2><a href=\"大众house-details.jsp?userName=${param.userName}&houseId=${house.id}\公众>${house.name}</a></h2></li></c:forEach></ul></body></html>

是不是清晰明朗了许多?

当然,JSP页面的开拓者必须知道传进这个页面的到底有哪些数据工具!

没错,这就相称于把数据的展示(视图层)给分离开来,你须要与后端(掌握器层和模型层)约定/设计好每一个JSP页面都有哪些数据工具。

然后,JSP页面的开拓者和后端(掌握器层和模型层)的开拓者就可以各自独立去开拓了。

剩下的页面改造

剩下的house-details.jsp和house-form.jsp该如何改造呢?大家可以先思考一下。

提示:JSP页面该当只关心取数据展示,而不应该关心如何查找到某个数据这种逻辑,该当把这种逻辑放到后端(掌握器层和模型层)。

我的改造是这样的,把原来这两个页面的如何查找到某个数据这种逻辑放到Filter中,前后端约定好这两个页面中存在target这个House工具,于是doFilter()方法中在将要求交给下个节点之前该当挂载上target这个House工具:

if (userName == null || userName.isEmpty()) {System.out.println(\"大众invalid user!\"大众);httpServletResponse.sendRedirect(\公众login.html\"大众);} else {String houseId = httpServletRequest.getParameter(\"大众houseId\公众);if (houseId != null && !houseId.trim().isEmpty()) {House target = findHouseById(houseId);//找不到怎么办?httpServletRequest.setAttribute(\"大众target\"大众, target);}chain.doFilter(request, response);}

其余,该当把如何查找某个房源的逻辑封装起来:

private House findHouseById(String houseId) {for (House house : mockHouses) {if (houseId.equals(house.getId())) {return house;}}return null;}

然后,这两个页面就极其大略了,house-details.jsp是这样的:

<%@ page language=\"大众java\"大众 contentType=\公众text/html; charset=UTF-8\"大众 pageEncoding=\"大众UTF-8\公众%><%@ include file=\"大众include.jsp\公众%><h2>${target.name}<a href=\"大众house-form.jsp?userName=${param.userName}&houseId=${target.id}\"大众>编辑</a></h2><h3>${target.detail}</h3><h4><a href=\公众houses.jsp?userName=${param.userName}\"大众>回到列表</a></h4></body></html>

house-form.jsp是这样的:

<%@ page language=\"大众java\"大众 contentType=\"大众text/html; charset=UTF-8\"大众 pageEncoding=\"大众UTF-8\"大众%><%@ include file=\"大众include.jsp\"大众%><form action=\"大众house-form.servlet\"大众 method=\"大众post\"大众><input type=\公众hidden\"大众 name=\"大众userName\公众 value=\"大众${param.userName}\公众/><input type=\"大众hidden\"大众 name=\"大众houseId\公众 value=\公众${target.id}\"大众/><label for=\公众house_name\"大众>房源名字:</label><input type=\公众text\"大众 id=\公众house_name\"大众 name=\"大众houseName\"大众 value=\"大众${target.name}\"大众 /><label for=\公众house_detail\"大众>房源详细信息:</label><input type=\公众text\公众 id=\"大众house_detail\"大众 name=\"大众houseDetail\"大众 value=\公众${target.detail}\公众 /><input type=\公众submit\公众 value=\"大众提交\公众 /></form></body></html>

可以看到,这两个页面只是取数据(target这个House工具)展示而已。

总结JSTL的终极目标是简化JSP开拓;JSTL的利用须要先声明某个库;JSTL的标签利用类似HTML标签和XML标签,语法规则可以查看JSTL规范;JSP页面利用JSTL和EL表达式基本可以实现大部分功能;EL表达式能够直接访问页面/要求/会话/运用这几个工具中挂载(即setAttribute()方法)的数据工具;EL表达式利用 ${ } ;EL中存在隐式工具,往后再先容;列表数据很常见很主要;列表数据采取JSTL的forEach标签来遍历(实际上也可以采取EL表达式,比如${mockHouses[i].id});前后端开拓的分离:前端只关心取数据如何展示;后端关心如何取数据并挂载到页面/要求/会话/运用这几个工具中;前后端需约定/设计好数据;