我的Java Web之路41 - JSTL初步使用
wxin55 2024-10-29 17:25 12 浏览 0 评论
本系列文章旨在记录和总结自己在Java Web开发之路上的知识点、经验、问题和思考,希望能帮助更多(Java)码农和想成为(Java)码农的人。
目录
- 介绍
- JSTL规范下载
- JSTL包含哪些库
- JSTL如何使用
- 租房网应用中使用JSTL
- JSTL相关的JAR包
- EL表达式访问列表的长度
- JSTL的forEach标签
- 剩下的页面改造
- 总结
介绍
上篇文章我们使用JSP技术对租房网平台进行了改造,也提到下面这样的代码有点奇葩:
<%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来进一步改造我们的租房网应用。
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,标签前缀通常使用:c
- XML处理:它的命名空间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,标签前缀通常使用:fn
JSTL如何使用
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});
- 前后端开发的分离:前端只关心取数据如何展示;后端关心如何取数据并挂载到页面/请求/会话/应用这几个对象中;
- 前后端需约定/设计好数据;
相关推荐
- 黑客工具sqlmap,带你了解什么师sql注入
-
1、sqlmap介绍sqlmap是一款支持MySQL,Oracle,PostgreSQL,MicrosoftSQLServer,MicrosoftAccess,IBMDB2,SQL...
- Web网络安全漏洞分析,SQL注入原理详解
-
本文主要为大家介绍了Web网络安全漏洞分析SQL注入的原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪一、SQL注入的基础1.1介绍SQL注入SQL注入就是指We...
- sql注入、文件上传、文件包含(sql注入数据提交的类型)
-
在owasp年度top10安全问题中,注入高居榜首。SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要...
- 比较常见类型漏洞讲解(三):SQL注入(一)
-
比较常见类型漏洞讲解(一)比较常见类型漏洞讲解(二):文件上传这里继续介绍比较容易找到的不同类型的漏洞。演示准备目标主机:Metasploitable2攻击目标:目标主机的dvwa系统攻击机:Kali...
- 警惕SQL注入:检测与防御的实战指南
-
在当今数字化的时代,软件系统的安全性至关重要。SQL注入作为一种常见且危害巨大的安全漏洞,给企业和用户带来了潜在的风险。对于测试人员来说,掌握发现和解决SQL注入漏洞的方法是保障软件质量和安全的...
- SQL注入的原理和危害(sql注入的原理及危害)
-
什么是SQL注入SQL注入是发生在web端的安全漏洞,实现非法操作,欺骗服务器执行非法查询,他的危害有会恶意获取,甚至篡改数据库信息,绕过登录验证,原理是针对程序员编写时的疏忽,通过执行SQL语句,实...
- 科普基础 | 最全的SQL注入总结(sql注入是干嘛的)
-
0x01SQL注入原理当客户端提交的数据未作处理或转义直接带入数据库,就造成了sql注入。攻击者通过构造不同的sql语句来实现对数据库的任意操作。0x02SQL注入的分类按变量类型分:数字型和字符...
- 产品经理必备IT技术知识之“什么是SQL注入攻击?
-
不少优秀的产品经理都会写一些简单的SQL语句进行数据查询的操作,但是会写SQL语句不代表能写好SQL语句。SQL语句写得不好,就会引发SQL注入攻击。SQL注入攻击是Web开发中最常见的一种安全问题,...
- 通过sql注入获取用户名和密码(联通光猫超级用户名超级密码获取)
-
1.啥是sql注入sql注入是一种通过操作输入来修改后台sql语句以达到利用代码进行攻击目的的技术2.生成sql注入漏洞的原因总结一句话:对前台传过来的参数没有进行有效的过滤,太相信前端传过来的参数...
- 什么是SQL注入攻击(SQL Injection)
-
1,定义:在构建数据库SQL语句时,攻击者在参数请求中注入恶意的SQL代码,并在在数据库中执行,操控数据库执行意图之外的操作。2,目的:窃取数据、修改数据、删除数据、绕过身份验证、权限提升,执...
- 浅谈SQL注入(sql注入的理解)
-
在关于SQL注入,百度的解释是这样的:SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知...
- sql注入(sql注入攻击是什么意思)
-
SQL注入分类1.数字型注入当输入的参数为整型时,则有可能存在数字型注入漏洞。假设存在一条URL为:HTTP://www.aaa.com/test.php?id=1可以对后台的SQL语句猜...
- SQL注入详解(sql注入总结)
-
现在大多数系统都使用B/S架构,出于安全考虑需要过滤从页面传递过来的字符。通常,用户可以通过以下接口调用数据库的内容:URL地址栏、登陆界面、留言板、搜索框等。这往往会出现安全隐患,为了更好的保护数据...
- 什么是sql注入,这些坑得避开(什么是sql注入,编程时如何避免)
-
1、sql注入是什么sql注入就是用户通过输入的参数,拼接到原先的sql中,成为sql的一部分,从而影响sql的功能和执行结果2、sql注入破坏力-小兵破坏力比如原先sql如下s...
- 金母鸡量化教学场:pandas—数据挖掘的Python库
-
如果你想充分发挥Python的强大作用,如果你想成为一名好的Python量化师,你应该先学好Pandas。今天就来了解什么是Pandas。与numpy易于处理同种类型数据不同,pandas更加的适合...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- hive行转列函数 (63)
- sourcemap文件是什么 (54)
- display none 隐藏后怎么显示 (56)
- 共享锁和排他锁的区别 (51)
- httpservletrequest 获取参数 (64)
- jstl包 (64)
- qsharedmemory (50)
- watch computed (53)
- java中switch (68)
- date.now (55)
- git-bash (56)
- 盒子垂直居中 (68)
- npm是什么命令 (62)
- python中+=代表什么 (70)
- fsimage (51)
- nginx break (61)
- mysql分区表的优缺点 (53)
- centos7切换到图形界面 (55)
- 前端深拷贝 (62)
- kmp模式匹配算法 (57)
- jsjson字符串转json对象 (53)
- jdbc connection (61)
- javascript字符串转换为数字 (54)
- mybatis 使用 (73)
- 安装mysql数据库 (55)