第三章 Spring集成 JSTL

视图层JSP中使用JSTL核心标签

在使用jsp作为视图技术的时候,我们会在页面中书写大量的java代码,这样其实不是非常的友好。在MVC的架构中,我们的目的是希望将模型层和视图层分开,视图层只用来做数据展示。由于视图层的本质就是HTML,而HTML则是标签化语言,因此很多模板技术也都使用”特殊标签"来展示数据,这些标签的特殊在于,它并不是HTML语言的范围,而是完全由模板开发者自定义的。因此,它不能在浏览器上正确执行,需要翻译成java代码,然后才能向浏览器输出最终的html内容。由此可见,模板技术的使用是为了方便开发者而创建的,目的是改变html和java代码”混编“的方式,让整个项目工程代码更加清晰。既然模板技术有这样的优势,那么jsp官方也就出品了这样的标签库,我们称之为JSTL(JSP标准标签库)。JSP 标签是一组与 HTML 标签相似,但又比 HTML 标签强大的功能标签。JSTL 用来简化 JSP 开发,可以使我们不用嵌入 Java 代码就能够开发出复杂的 JSP 页面。

我们可以从Apache官网的标准标签库中下载的二进包,地址为:https://archive.apache.org/dist/jakarta/taglibs/standard/binaries/

我们选择 “jakarta-taglibs-standard-1.1.2.zip” 进行下载就行啦。下载完毕后解压缩后在lib目录下就会发现两个JAR文件:“jstl.jar” 和 “standard.jar”,如下所示:

JSTL 包含 5 类标签库:core 标签库、fmt 标签库、fn 标签库、XML 标签库和 SQL 标签库。这 5 类标签库基本覆盖了 Web 开发中的所涉及的技术展示。 本章节我们只介绍core 标签库的使用,我们继续使用SpringMVCDemo工程。首先两个jar文件:jstl.jar和standard.jar文件复制到项目的WEB-INF/lib/目录下。

在使用标签库之前,我们必须在JSP页面的顶部使用<%@ taglib %>指令定义引用的标签库和访问前缀。使用核心标签库的taglib指令格式如下:

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

核心标签库主要用于完成JSP页面的常用功能,包括表达式标签,URL标签,流程控制标签和循环标签共4种标签。

表达式标签包括 <c:out>,<c:set>,<c:remove>和<c:catch>

URL标签库包括 <c:import>,<c:redirect>,<c:url>和<c:param>

流程控制标签包括 <c:if>,<c:choose>,<c:when>和<c:otherwise>

循环标签包括 <c:forEach>和<c:forTokens>

接下来,我们就注意介绍这些标签如何使用。

首先是 <c:out> 将表达式的值输出到页面,相当于JSP表达式 <%= 表达式 %>

语法格式:<c:out value="<string>" default="<string>" escapeXml="<true|false>"/>

value就是要输出的内容 ,default 是输出的默认值,escapeXml 表示是否忽略XML特殊字符,其中后两项可以没有。如果我们要输出上个章节中helloController传递给hell.jsp中的message信息的话,可以这么写。

<h1>${message}</h1>
<h2><c:out value="${message}" /></h2>

这里,我们仍然要借助EL表达式来获取变量message的内容。如果直接在value中写message的话,<c:out>标签只会原样输出字符串"message",并不会将其作为一个变量使用。如果只是简单的显示变量值的话,可以直接使用EL表达式,而不使用该标签,这样更加简洁。我们运行当前工程,查看hello.jsp页面显示效果

接下来是<c:set> 在指定范围内定义变量

语法格式:<c:set var="<string>" value="<string>" scope="<string>"/>

var是变量的名称,value 是变量的值 ,scope 是变量的作用域。我们可以使用<c:set>设置一个新变量,然后使用<c:out>输出这个新变量,使用方式如下:

<c:set var="name" value="张三" />
<p><c:out value="${name}" /></p>

接下来是<c:remove> 从指定的jsp范围种移除指定的变量。

语法格式:<c:remove var="<string>" scope="<string>"/>

var就是变量的名称,scope就是变量的作用域。那么变量的作用域到底是什么呢?在之前的JSP课程中,我们应该涉及过作用域这一块的内容。这里的作用域主要是page, request, session, application四种,范围也逐渐增大。page代表该变量只在当前页面有效,request表示该变量在当前请求范围内有效,session表示该变量在会话范围内有效,application表示该变量在整个应用范围内有效。作用域影响的是变量的生命周期,也就是变量在什么时候被销毁掉。<c:set>标签默认的作用域是page,也就是说,页面改变后,其定义的变量就会被销毁。关于这个标签,我们就不在演示了。因为在大部分情况中,我们都不会在JSP页面中设置新的变量。即便会这样做,这个新的变量也基本上是page作用域,我们也没有必要显式的使用<c:remove>去销毁它(让它自生自灭即可)。

接下来是<c:catch> 捕获异常,相当于try…catcha语句。

语法格式:<c:catch var="<string>">...</c:catch>

我们一般不会在JSP页面中进行异常捕获,所以很少使用该标签。

接下来介绍<c:import> 引入其他动态或静态页面,相当于<jsp:include>行为标签所具有的功能。

语法格式:<c:import url="<string>" var="<string>" scope="<string>" />

url 就是导入资源的URL,可以是相对路径和绝对路径;var 用于存储资源内容的文本的变量;scope 是变量的的作用域。接下来,我们就来使用这个标签引入另一个jsp文件试试。首先,创建一个 "part.jsp",内容如下

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<p>这里只是一部分内容</p>

没错,这个文件不是一个完整的HTML文档,里面就是一个html片段而已。我们要将它引入到hello.jsp里面

<c:import url="part.jsp" />

我们发现,它和<jsp:include>非常的相似,运行项目后效果

接下来就是 <c:redirect> 标签通过自动重写URL来将浏览器重定向至一个新的URL。

语法格式:<c:redirect url="<string>" />

不用详细介绍了,url就是重定向的地址。

一般情况下,我们不会直接在jsp页面进行重定向的操作。

接下来就是<c:url> 构造一个URL,我们可以将它指定给超链接的href属性使用。

语法格式:<c:url value="<string>" var="<string>" scope="<string>" />

其中value就是url的内容,var和scope是存储url的变量,可以不使用。

<a href="<c:url value='hello.do' />">test</a>

最终会输出的内容为

<a href="hello.do">test</a>

我们发现没有太大的差距,还不如直接写“hello.do”来的直接呢。

接下来是<c:param> 为其他标签提供参数,可以配置上面的<c:url>一起使用,构造有参数的url。

语法格式:<c:param name="<string>" value="<string>"/>

我们的参数基本的都是K-V的形式,name就是K,value就是V, 非常的简单,具体使用方式如下

<c:url value="hello.do" var="link">
	<c:param name="name" value="zhangsan" />
	<c:param name="age" value="30" />
</c:url>

<a href="${link}">test</a>

我们使用<c:url>生成的链接放入到变量link中,然后在超链接中使用EL表达式读取这个link变量,最终我们的超链接的地址就是如下这样。

<a href="hello.do?name=zhangsan&age=30">test</a>

我们发现这没有太大的差距,还不如直接拼接url来的方便和快捷。

接下来,我们继续介绍<c:if> 分支判断,相当于if语句,没有else标签。

语法格式:<c:if test="<boolean>" var="<string>" scope="<string>">...</c:if>

其中test就是条件表达式,它的结果应该是一个布尔值;var和scope是存储布尔值的变量而已,可以不写。这个<c:if>标签虽然简单,但是会经常的大量的使用。因此,我们必须熟练使用这个标签。举一个简单的例子,我们在Controller控制器层来处理数据,然后传递给jsp页面上,如果数据数据出现问题,我们的jsp页面可能直接崩溃掉。在我们本章节中,我们的HelloController向hello.jsp传递的message数据变量可能是一个空值,虽然它不会让jsp页面崩溃,但是可能对访问的用户产生不好的体验。因为,页面上会输出一个空白。我们可以修改一下

<div>
	<c:if test="${message eq ''}">空</c:if>
	<c:if test="${message ne ''}">${message}</c:if>
</div>

然后,我们在调整一下HelloController里面的代码

// TODO Auto-generated method stub
ModelAndView mv = new ModelAndView();
mv.addObject("message", "");
//mv.addObject("message", "hello,springmvc!");
//mv.addObject("message", helloDao.getMessage());
mv.setViewName("/hello.jsp");
return mv;

我们运行查看结果

这个分支标签的缺陷在于没有else的部分,有时候使用情况不是很方便。 关于分支判断,还有<c:choose> , <c:when> 和 <c:otherwise> 三个, 大家可以自己研究如何使用。

接下来,我们重点说说<c:forEach> 循环标签的使用,它也是经常的大量的使用,可以遍历数组和集合。

forEach 语法格式:<c:forEach items="<object>" var="<string>" varStatus="<string>" begin="<int>" end="<int>" step="<int>">......</c:forEach>

其中 items 就是要被循环的数组或集合,var代表循环的每一个元素的变量名称,varStatus 代表循环状态的变量名称,beign,end和step分别代表计数循环开始值,结束值以及步长。我们还是以实际案例说明该标签的使用。

<c:forEach var="i" begin="1" end="5">
	<c:out value="${i}" />
</c:forEach>

以上循环就是输出1,2,3,4,5数字,属于计数型循环,使用相对来说比较少,我们可以查看运行结果。

接下来,我们演示如何读取数组和列表,首先我们需要从Controller传递过来数组和列表数据,如下所示

		// TODO Auto-generated method stub
		ModelAndView mv = new ModelAndView();
		mv.addObject("message", "");
		//mv.addObject("message", "hello,springmvc!");
		//mv.addObject("message", helloDao.getMessage());
		
		int arr[] = {1,3,5,7,9};
		mv.addObject("arr", arr);
		
		List<String> list = new ArrayList();
		list.add("a");
		list.add("b");
		list.add("c");
		mv.addObject("list", list);

		mv.setViewName("/hello.jsp");
		return mv;

我们分别向hello.jsp页面传递了arr数组和list列表两种数据,接下来就需要在hello.jsp中读取这两种数据。

<div>
<c:forEach items="${arr}" var="item">
	<span>${item}</span>
</c:forEach>
</div>

<div>
<c:forEach items="${list}" var="item">
	<span>${item}</span>
</c:forEach>
</div>

我们运行工程,查看效果

其实对于数组和列表中的元素,还可以更加复杂一下,比如就是一个java类。我们依然可以使用上面的方式读取到。只不过元素item就会对应上这个java类,我们可以通过EL表达式来读取类属性变量,例如 ${item.name}

这里,我们使用一个Map对象来说明上面的问题。同样,我们调整HelloController中的数据传递。

		List<Map<String,String>> map = new ArrayList();

		Map map1 = new HashMap();
		map1.put("name", "张三");
		map1.put("age", 30);
		map.add(map1);

		Map map2 = new HashMap();
		map2.put("name", "李四");
		map2.put("age", 31);
		map.add(map2);

接下来,我们来读取上面的内容

<div>
<c:forEach items="${map}" var="item">
	<span>${item.name} ${item.age}</span>
</c:forEach>
</div>

我们运行工程,查看效果

接下来说说<c:forEach> 中的 varStatus 属性,它包含如下值

current	当前这次迭代的(集合中的)项
index	当前这次迭代从 0 开始的迭代索引
count	当前这次迭代从 1 开始的迭代计数
first	用来表明当前这轮迭代是否为第一次迭代的标志
last	用来表明当前这轮迭代是否为最后一次迭代的标志
begin	属性值
end		属性值
step	属性值

这个属性有时候,对我们帮助很大,比如我们在页面上使用列表来展示集合数据的时候,需要做隔行变色的效果。也就是说,当循环元素的下标是偶数的时候,我们可以设置它的背景色,这样就与奇数的元素区分开了。

<div>
<c:forEach items="${map}" var="item" varStatus="status">
	
	<c:if test="${status.count % 2 eq 0}">
	<span style="color:red">${item.name} ${item.age}</span>
	</c:if>
    
	<c:if test="${status.count % 2 eq 1}">
	<span>${item.name} ${item.age}</span>
	</c:if>
	
</c:forEach>
</div>

我们让偶数的数据显示红色,运行工程效果如下

最后我们说一下<c:forTokens> 可以分割字符串的循环标签,我们直接使用案例说明吧。

<div>
<c:forTokens items="hello:java:jsp:spring" delims=":" var="item">
	<p>${item}</p>
</c:forTokens>
</div>

上面的代码其实就是按照冒号来分割字符串,然后输出每一个分割元素,运行工程效果如下

如果想使用变量读取字符串的话,可以这样写

<div>
<c:set var="str" value="hello:java:jsp:spring" />
<c:forTokens items="${str}" delims=":" var="item">
	<p>${item}</p>
</c:forTokens>
</div>

效果是一样的,不在给出截图了。

整体项目下载地址: https://download.youkuaiyun.com/download/richieandndsc/89876567

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值