Head First JSP---随笔七

11 篇文章 0 订阅
11 篇文章 0 订阅

强大的定制标记(JSTL)

有时只是EL或标准动作还不够。如果我们想循环处理一个数组中的数据,并在一个HTML表中每一行显示一项,该怎么做?这时,就需要强大的JSTL了。


使用标记库建立JSP页面

9.1 描述“taglib”指令的语法和语义:包括标准标记库的相应“taglib”指令和标记文件的相应“taglib”指令。
9.2 创建定制标记结构来支持给定的设计目标。
9.3 对于以下JSP标准标记库(JSTL v1.1)标记,明确这些标记的语法,并描述标记的动作语义
1. 核心标记:out,set,remove和catch
2. 条件标记:if,choose,when和otherwise
3. 循环标记:forEach
4. URL相关的标记:url

安装JSTL 1.1
这里写图片描述


使用c:out标记

可以显式地声明转换XML实体:<c:out value="${perfix.name} escapeXml="true"/>,则说明将EL表达式的HTML按文本显示。
可以显式地声明不转换XML实体:<c:out value="${perfix.name}" escapeXml="false"/>,则说明将EL表达式所获取到的HTML标记都进行计算,不按文本显示(例如:EL获得到的字符串是<br/><br/>,则将计算出2个换行)。

HTML需要转换的特殊字符:
这里写图片描述

这里指出:escapeXml默认为true


跨网站攻击(cross-site hacking)或跨网站脚本攻击(cross-site scripting)

这种攻击是指一个用于使用你的Web应用作为传输机制向另一个用户的web浏览器发动攻击。

如图:
攻击


default属性设置一个默认值

假设我们在EL表达式计算为null的时候希望打印出一个默认值。

有两种做法:
(1)<c:out>单标签提供一个default属性,是<c:out value="${user}" default="guest"/>这样的形式。
(2)<c:out>双标签可以这样做:<c:out value="${user}">guest</c:out>


不用脚本(scriptlet)循环的c:forEach标记

这里写图片描述
注意:元素和数组


c:forEach剖析

<c:forEach>标记可以循环数组和集合中的每一个元素:(如下)
这里写图片描述
还有一个循环计数器(varStatus):
这里写图片描述
记住还需要count


嵌套c:forEach标记

这里写图片描述
注意嵌套时的属性值


JSTL注意的几点

1.问:你怎么知道”varStatus”属性是这样一个类的实例,你是怎么知道它有一个”count”性质的?
答:JSTL 1.1规范告诉我的
2.问:能改变迭代的步长吗?例如i+=3?
答:可以的,JSTL 1.1中有这些问题的答案,改变步长可以使用step属性
3.一个需要注意的地方:作用域!
注意点


c:if条件包含

所有人都得到同样的页面,但是成员在页面上能“看到”更多东西。
这里写图片描述
这里指出:并没有一个“else”的字句


c:choose标记

这里写图片描述


c:set标记的var

“var”版本用于设置属性变量(pageScope,requestScope,applicationScope,session)。

这里指出:var必须是一个直接量,不能使EL表达式!
这里写图片描述


c:set标记的target

“target”版本用于设置对象性质(bean,Map)
这里写图片描述


c:set的要点和技巧

  1. <c:set>不能同时有“var”和“target”属性。
  2. “scope”是可选的,如果没有使用这个属性,则默认为页面(page)作用域
  3. 如果“value”为null,“var”指定的属性将被删除。
  4. 如果“var”指定的属性不存在,则会创建一个属性,但仅当“value”不为null时才会创建新属性。
  5. 如果“target”表达式为null,容器会抛出一个异常。
  6. “target”中要放入一个能解析为实际对象的表达式。如果放入一个String直接量(表示bean或Map的“id”名),这是不行的。换句话或,“target”并非用来放bean或Map的属性名,而是用于指定具体的属性对象(target的值可以是一个bean或Map,但是不能为直接量,下面的话验证了这点)。
  7. 如果“target”表达式不是一个Map或bean,容器会抛出一个异常
  8. 如果“target”表达式是一个bean,但是这个bean没有与“property”匹配的性质,容器就会抛出一个异常。记住EL表达式${bean.property}也会抛出一个异常

c:remove标记

这里写图片描述


c:import标记

<c:import>标记让我们只要知道url就可以把别人的页面当做自己页面的一部分(注意最后一行)。
这里写图片描述


c:param标记

<jsp:param>类似。
这里写图片描述


c:url可以满足所有超链接需求

如果客户浏览器不支持cookie,我们就需要url重写。
这里写图片描述
这样方便多了


如果URL需要编码

这里写图片描述


建立自己的错误页面

这里写图片描述


在DD中配置错误页面

如果像上面那样写的话,需要在所有的JSP文件中写上指定的错误页面,岂不是要累死?

这个时候DD中允许你配置错误页面,对所有的JSP而言。

在DD中可以根据<exception-type>或状态码<error-code>声明错误页面。

这里写图片描述


错误页面得到一个exception的对象

这里写图片描述
这样,对我们页面排错就有了可靠的工具。


c:catch来恢复页面,就像try/catch一样

一个<c:catch>会同时作为try和catch部分,这听上去有点怪,确实没有单独的try标记。我们要把有风险的EL或标记调用(或其他部分)包在<c:catch>的体中,异常就会在这里被捕获。不过,不能把它当成一个catch块,因为一旦异常发生,控制就会跳至<c:catch>标记体的最后。

这里写图片描述


可以将异常设置为一个属性

对于Web应用错误处理,只有正式指定错误页面(isErrorPage=true)才能得到异常对象。
这里写图片描述

如果想要在<c:catch>标记结束后访问异常,可以使用可选的var属性
这里写图片描述


c:catch注意

这里写图片描述


JSTL的标记库

JSTL相当庞大。1.1版本有5个库,其中4个是定制标记库,还有一个提供了大量用于串处理的函数。
这里写图片描述


使用非JSTL的标记库

创建标记的支持代码并不轻松(支持代码就是在JSP中放入标记时所需要调用的Java代码)。

要使用定制库,必须阅读TLD。我们想知道的一切都在这里。

这里写图片描述


理解TLD

这里写图片描述
可以看出每个标记都对应着一个name和一个类和体中能否为空,并且可以设置它的属性以及这个属性能否是一个表达式。


使用定制“advice”标记

“advice”标记时一个简单的标记,它有一个属性(用户名),并打印一个随机的建议。这非常简单,使用一个普通的EL函数(有一个静态方法 getAdvice(String name))就完全可以做到,但我们还是把它做成一个简单的标记。
这里写图片描述


定制标记处理器

这个简单的标记处理器拓展了SimpleTagSupport,而且实现了两个关键方法:doTag()和setUser,doTag()是完成具体工作的方法,setUser()方法接收属性值。
这里写图片描述
可以知道如果利用定制标记,方法名就必须是doTag()。也就是说,一个标记对应一个类。


注意rtexprvalue

如果<rtexprvalue>为false,或者未定义<rtexprvalue>,那么属性值只能是一个String直接量。
这里写图片描述

还需要注意属性类型:
这里写图片描述


rtexprvalue不只是针对EL表达式

可以使用3种表达式:
这里写图片描述


标记体能放什么?

首先看看TLD中标记配置<body-content>能放什么
这里写图片描述
对于没有体的标记,有3种调用方法
这里写图片描述


标记处理器、TLD和JSP

标记处理器开发人员要创建TLD,告诉容器和JSP开发人员如何使用这个标记。JSP开发人员并不关心TLD的<tag-class>元素;这是容器要考虑的事情。JSP开发人员主要关心uri、标记名和标记语法。标记能有体吗?属性必须是一个String直接量吗?属性能使一个表达式吗?这个属性是可选的吗?表达式要计算为何种类型?

要部署和运行一个使用了标记的Web应用,只需要这3部分——标记处理器类、TLD和JSP。
这里写图片描述


taglib的uri属性只是一个名,而不是一个位置

TLD中的<uri>要与taglib指令中的uri匹配!
这里写图片描述


容器建立一个映射

在JSP 2.0之前,开发人员必须为TLD中的<uri>与TLD文件的具体位置之前指定一个映射。例如一个JSP页面有<%@ taglib prefix="mine" uri="randomThings"%>,则部署描述文件(web.xml)必须告诉容器到哪里找有匹配的TLD文件,如下:
这里写图片描述

在JSP 2.0出现后,DD中已经没有<taglib>标签了!所以,容器会自动建立TLD和<uri>名之间的映射

这是怎么做到的?答案是:在能放TLD的所有特定位置上找一遍。部署一个Web应用时,只要把TLD放在容器会搜索位置上,容器就会发现这个TLD,并为标记库建立一个映射。


容器会在4个位置查找TLD

这里写图片描述


如果JSP使用了多个标记库

要记住几点:

  1. 确保taglib uri名是唯一的。换句话说,多个指令不能有相同的uri值。
  2. 不要使用保留的前缀。
    这里写图片描述

本章完

因为感冒,所以看这章的时候有点累。。不过加油!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值