《Head First Servlets & JSP》-9-使用JSTL

安装JSTL1.1的说明

JSTL1.1不是JSP2.0规范的一部分,能访问servlet和JSP API并不意味着能访问JSTL。

使用JSTL之前,需要将jstl.jar文件安装到Web应用的WEB-INF/lib目录,即每个Web应用都需要JSTL的一个副本。

不用脚本实现一个循环——c:forEach

servlet代码:

  • 使用脚本实现,很不好

    若想要在JSP页面中显示其中的各个元素,使用脚本的方式如下:

  • 使用JSTL c:forEach实现

    c:forEach标记提供了一种简单的方法来迭代处理数组和集合,如Collection、Map或者用逗号分隔的String。

    那么JSP页面代码变为:

    甚至可以使用可选的varStatus属性得到循环计数器:

    varStatus建立了一个新变量,其中保存javax.servlet.jsp.jstl.core.loopTagStatus的一个实例,而loopTagStatus类有一个count属性,这一切都在JSTL规范文档中。

    c:forEach标记还可以嵌套使用,如一个List中保存了若干数组,当遍历这些数组中的元素时…。

使用c:if完成条件包含

若对于一个评论页面,只有会员可以参与评论,非会员则只能浏览评论。

评论列表(commentList.jsp):

参与评论(inputComments.jsp):

带有else的判断:c:choose和它的小伙伴c:when和c:otherwise

毕竟c:if没有else,虽然可以使用多个if应对,但是很难看,况且这样一来也没有一个默认的选择(即otherwise的作用)。

  • JSP中部分代码:

    与Java中的switch有所不同,c:choose只能运行分支中的一个(包括when和otherwise),而switch在缺少break的时候可能运行多个分支。

属性设置c:set标记

鉴于jsp:setProperty标记只能设置bean的性质,而JSTL的c:set可以对bean、Map、变量等多个性质赋值。

  • 用c:set设置属性变量var

    注意,当值计算为null,变量会被删除。如原先有一个名为Fido的变量属性,而${person.dog}计算为null,这个Fido属性就会被删除,即使不指定scope,也会按照顺序在页面作用域、请求作用域、会话作用域、上下文作用域中找到并删除这个Fido!

  • 对bean和Map使用c:set

    target必须计算为一个对象!而不是表示属性名的String直接量。

    这意味着target需要一个EL表达式(如上)或者一个脚本表达式(<%= %>),或者jsp:attribute。

c:remove来删除一个属性

虽然c:set在值为null时可以删除属性,但是专门删除属性时用c:remove:

复用页面的第三种方式——c:import

  • 复习一下前两种方式

    第一种方式:include指令

    <%@ include file="Header.html"%> 一般是静态的布局模板,如html页面,故用file属性。

    第二种方式:include标准动作

    <jsp:include page="Header.jsp"> 一般是JSP动态内容,故用page属性。

  • 第三种方式:JSTL的c:import标记

    <c:import url="http://www.google.com" /> 这里是url属性。

    与前两种方式不同,它可以超出当前容器范围之外!

  • 包含个性化参数c:param

关于会话跟踪:URL重写/编码——c:url

JSP中会话跟踪是自动发生的(除非把session属性指定为session=”false”)。但是,当客户不支持cookie的时候,需要重写URL的方式增加会话ID到URL。

  • 以前,在servlet中的URL重写是这样的

  • 在JSP中也可以做同样的事情

  • URL编码——c:param

    上述重写过程,没有特殊符号,因此不用进行URL编码。但是,若包含查询串,则难保不出现特殊符号,就像这样:

    那么在c:url的体中使用c:param,可完成编码:

    这样就可以查看编码后的URL:

    ${inputURL}

建立自己的错误页面

  • 指定的错误页面errorPage.jsp

  • 会抛出异常的坏页面badPage.jsp:

    当访问badPage.jsp的时候,因为抛出异常,所以跳转到errorPage.jsp.

  • 通过DD中的error-page标记可以为整个Web应用指定多样化的错误页面

    一个普通的错误页面DD配置:

    更为明确的异常声明DD配置:

    或者根据HTTP状态码声明错误页面:

    DD 中的error-page是全局的,若某个JSP页面单独指定明确的errorPage page指令,那么容器就会优先使用page指令进行错误页面跳转。

错误页面的一个额外隐式对象:exception

若想要给用户提示错误信息时(通常不会提示这样的信息),则可以在错误页面中使用隐式对象exception:

一般的页面不会有隐式对象exception的,只有明确使用page指令中的isErrorPage=”ture”属性的页面才有此隐式对象。

想要自己捕捉异常,而不想抛出错误——c:catch

  • 使用c:catch标记捕捉异常

  • 自己捕捉的异常是可以访问的,只要定一个异常名字即可。即使本身不是异常页面(isErrorPage=”ture”):

  • 和try块一样,出现异常后,c:catch体中余下的部分不再运行

使用非JSTL的标记库——定制库

想要使用定制库,那么必须阅读TLD。当然,这只是使用它,若开发定制库(即开发支持标记的Java代码),不是这里的任务。

  • 理解TLD

    以下tld文件描述了一个标记:advice

  • 使用标记的JSP,及其与tld文件的对应关系

  • 注意rtexprvalue

    tag/attribute/rtexprvalue节点很重要,因为它会告诉你属性的值是在转换时计算,还是在运行时计算。

    若其值为false或未定义,那么属性值只能是一个String直接量,而不能是上图中的user=”${userName}”这种表达式!

    rtexprvalue不只是针对EL表达式,可以使用如下几种方式:

  1. EL表达式

  2. 脚本表达式

  3. attribute标准动作

    注意,即使tag/body-content声明为empty,仍可以使用jsp:attribute在标记的体中放属性!

  • 标记体body-conten里能放什么

    标记体body-conten中可以放如下值,只有当标记body-content元素值不是empty时,标记才能有体。

    对于没有体的标记(即body-conten为empty),有3中调用方法(包括上述的attribute标准动作):

  • taglib中的uri,只是一个名字

    上面的uri是randomThings,可知是一个名字。即使是uri=”http://java.sun.com/jsp/jstl/core”这种长串,也仅仅是一个名字,而不是一个位置。

  • tld文件的位置在哪里声明?

    在JSP2.0之前,会在web.xml中有个taglib-location项,但是现在不需要了。容器会在4个位置查找TLD:

  1. 直接在WEB-INF目录中查找
  2. 直接在WEB-INF的一个子目录中查找
  3. 在WEB-INF/lib下的JAR文件中的META-INF目录中查找
  4. 在WEB-INF/lib下的JAR文件中的META-INF目录的子目录中查找
  • 当JSP使用了多个标记库

    每个TLD要有一个单独的taglib指令;

    确保taglib指令名是唯一的;

    不要使用保留前缀如jsp/jspx/java/javax/serlvet/sun/sunw等

标记处理器、TLD和JSP关系

定制标记处理器

上面是如何使用advice定制标记的,那么现在稍微看看该标记的支持代码是怎么写的。

  • 完成标记工作的Java类foo.AdvisorTagHandler.java

    这个简单的标记处理器扩展了SimpleTagSupport,实现了两个关键方法:doTag()和setUser()。

    doTag()是完成具体工作的方法,setUser()是接受属性值的方法。详情如下:

EL函数 vs 标记处理器

  • 都是Java类
  • 都需要放在WEB-INF/classes文件下的某个路径下
  • 都要在TLD文件中进行映射
  • EL函数在TLD中的映射是
  • 标记处理器在TLD中的映射是
  • EL函数可以定义任意名称的静态方法
  • 标记处理器方法名必须是doTag()

《Head First Servlets & JSP》-9-使用JSTL

时间: 2024-10-29 19:05:31

《Head First Servlets & JSP》-9-使用JSTL的相关文章

《Head First Servlets & JSP》-8-无脚本的JSP

以前servlet和JSP交互的代码 servlet代码示例: JSP代码示例: 若属性不是一个String而是一个Bean呢? 一个简单的JavaBean servlet代码示例: JSP代码示例: 或者这么写: JSP中不要出现脚本 使用标准动作的JSP 标准动作jsp:useBean详解 scope默认是page作用域,那么在上述示例代码中可能出现问题:找不到person对象! 标准动作jsp:getProperty详解 jsp:useBean还可以创建一个bean 以下标准动作标记: 会

《Head First Servlets & JSP》-13-过滤器和包装器

过滤器是什么 与servlet非常类似,过滤器就是java组件,请求发送到servlet之前,可以用过滤器截获和处理清求,另外 servlet结束工作之后,在响应发回给客户之前,可以用过滤器处理响应. 容器根据DD中的声明来确定何时调用过滤器.在DD中,部署人员要建映射.明确对于哪个请求URL模式要调用哪些过滤器.所以,要由部署人员(而不是程序员)来确定哪些请求或响应应当由哪些过滤器处理. 过滤器要做的事情 只有一个过滤器接口:Filter,根据使用方式,可完成诸如以下工作: 请求过滤器可以完成

《Head First Servlets & JSP》-5-属性和监听

Servlet初始化参数 在DD文件(web.xml)中 Servlet参数在 在Servlet代码中 在Servlet初始化之前不能使用Servlet初始化参数 一旦有了一个ServletConfig引用,就可以调用getInitParameter()方法,不过 不能从构造函数调用这个方法!因为容器只调用构造函数还未调用init()之前,它还不算一个完整的Servlet(薛定谔Servlet). Servlet初始化参数只能赌一次--就是在容器初始化Servlet的时候 容器建立一个Servl

《Head First Servlets & JSP》-2-概述

什么是容器 Servlet没有main()方法,他们受控于另一个Java应用,这个java应用称为容器(Container). Web服务器应用(如Apache)得到一个指向Servlet的请求(如何判断是一个Servlet请求而不是一个静态HTML页面请求?)时,服务器不是把这个请求交给Servlet本身,而是交给部署该Servlet的容器.由容器向Servlet提供HTTP请求和响应,而且要由容器调用Servlet的方法(如doPost()或deGet()). 注意,我们目前使用Tomcat

《Head First Servlets & JSP》-11-Web应用部署

Web目录 WAR文件 WAR文件只是Web应用结构的一个快照,采用了一种更可移植的压缩形式. 建立WAR文件时,就是把整个Web应用结构(去掉Web应用上下文目录,就是把WEB-INF之上的一级目录去掉)压缩起来,给定一个.war扩展名. 容器如何知道Web应用的名字/上下文呢?Tomcat中,WAR文件名就是了! 在一个WAR文件中,可以在META-INF/MANIFEST.MF文件中声明库依赖性(和直接放在WEB-INF/lib下有何区别?后文见分晓). 部署后的WAR文件的样子 使静态内

《Head First Servlets & JSP》-3-1st servlet MVC demo

项目结构 用户首页 form.html <html> <body> <h1 align='center'>Beer Selection Page</h1> <form method="post" action="SelectBeer.do"> Select <p> Color: <select name="color" size="1"> &l

《Head First Servlets & JSP》-6-会话管理

容器怎么知道客户是谁 Http协议是无状态连接,客户浏览器与服务器建立连接.发出请求.得到响应,然后关闭连接.即,连接只针对一个请求/响应. 对容器而言,每个请求都来自于一个新的客户. 客户需要一个唯一的会话ID IP不能唯一标示Internet上特定的用户 比如公司网络内的用户为一个IP:而IP地址也只是路由的地址:用户换了一台设备的情况: 客户和容器如何交互会话ID信息 容器必须以某种方式吧会话ID作为响应的一部分交给客户,而客户必须把会话ID作为请求的一部分发回: 最简单而且最常用的方式是

《Head First Servlets & JSP》-10-定制标记开发

标记文件:很想include,但是比include更好 建立和使用标记文件的最简方法 取一个被包含文件(如Header.jsp),把它重命名为带有一个.tag扩展名(Header.tag): 把标记文件(Header.tag)放在WEB-INF目录下一个名为tags的目录中: 在JSP中放一个taglib指令(有一个tagdir属性),并调用这个标记: 如何向标记文件发送参数? 对于标记文件,发送的不是请求参数,而是标记属性! 在JSP中调用标记: 在标记文件中使用属性: 如何定义标记文件中所需

《Head First Servlets & JSP》-6-会话管理-listener etc. demo

工程结构 上下文参数示例 示例程序展示了如何从上下文读取参数,并在上下文监听器中生成属性对象和在上下文中设置属性. 建立一个简单的JavaBean对象作为属性:Dog.java package com.example.entities; /** * Created by LTN on 2016/11/2. */ public class Dog { private String breed; public Dog(String breed) { this.breed = breed; } pub