自定义标签
1 HelloWorld
创建一个标签处理器类:实现SimpleTag接口
在WEB-INF文件下面创建一个.tid(标签库描述文件)为扩展名的xml文件并考入固定部分
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <!-- 描述TLD文件 --> <description>MyTag 1.0 core library</description> <display-name>MyTag core</display-name> <tlib-version>1.0</tlib-version> <!-- 建议在JSP页面上使用的标签的前缀 --> <short-name>atguigu</short-name> <!-- 作为tld文件的ID ,用来唯一表示当前的TLD文件,多个tld 文件的URI 不能重复。通过JSP页面的taglib表签uri属性来应用--> <uri>http://www.atguigu.com/mytag/core</uri> <!-- 描述自定义的HelloSimpleTag标签 --> <tag> <!-- 标签名:JSP页面使用标签的名字 --> <name>hello</name> <!-- 标签所在的全类名 --> <tag-class>com.atguigu.javaweb.tag.HelloSimpleTag</tag-class> <!-- 标签体的类型 --> <body-content>empty</body-content> </tag> </taglib>
并对description,display-name,tlib-version,short-name,uri做出修改
在tld文件中描述自定义标签
<!-- 描述自定义的HelloSimpleTag标签 -->
<tag>
<!-- 标签名:JSP页面使用标签的名字 -->
<name>hello</name>
<!-- 标签所在的全类名 -->
<tag-class>com.atguigu.javaweb.tag.HelloSimpleTag</tag-class>
<!-- 标签体的类型 -->
<body-content>empty</body-content>
</tag>
在jsp页面使用自定义标签
》使用taglib指令导入标签库描述文件:
<%@taglib uri="http://www.atguigu.com/mytag/core" prefix="atguigu" %>
》使用标签:<atguigu:hello/>
setJSPContext:一定会被JSP引擎所调用,先于doTag,把代表JSP引擎的pageContext传给标签处理器类
private PageContext pageContext; //JSP引擎调用,代表JSP页面PageContext对象传入 //pageContext 可以获取JSP页面的其他八个隐含对象 //所以凡是JSP页面可以做的标签处理器都可以完成 @Override public void setJspContext(JspContext arg0) { System.out.println(arg0 instanceof PageContext); this.pageContext = (PageContext) arg0; }
带属性的自定义标签:
》现在标签处理器类中定义setter方法。建议把所有的属性都设置为String类型
private String value; private String count; public void setValue(String value) { this.value = value; } public void setCount(String count) { this.count = count; }
在tld描述文件中描述属性:
<!-- 描述当前标签的属性 -->
<attribute>
<!-- 属性名 ,需和标签处理器类的setter方法定义的属性相同-->
<name>value</name>
<!-- 该属性是否被必须 -->
<required>true</required>
<!-- rtexprvalue: runtime expression value 当前属性是否可以接受运行时表达式的动态值 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
在页面中使用属性,属性名同tld文件中定义的属性名字
<atguigu:hello value="${param.name }" count="10"/>
通常情况下开发简单标签直接继承SimpleTagSupport就可以了,可以直接调用自己的getter方法得到的对应的API
public class SimpleTagSupport implements SimpleTag { private JspTag parentTag; private JspContext jspContext; private JspFragment jspBody; public SimpleTagSupport() { // NOOP by default } @Override public void doTag() throws JspException, IOException { // NOOP by default } @Override public void setParent( JspTag parent ) { this.parentTag = parent; } @Override public JspTag getParent() { return this.parentTag; } @Override public void setJspContext( JspContext pc ) { this.jspContext = pc; } protected JspContext getJspContext() { return this.jspContext; } @Override public void setJspBody( JspFragment jspBody ) { this.jspBody = jspBody; } protected JspFragment getJspBody() { return this.jspBody; } }
正则表达式
package com.atguigu.javaweb.tag; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.regex.Pattern; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.SimpleTagSupport; public class ReadFuleTag extends SimpleTagSupport{ //相对与当前WEB应用的根路径的文件名 private String src; public void setSrc(String src) { this.src = src; } @Override public void doTag() throws JspException, IOException { PageContext pageContext = (PageContext) getJspContext(); InputStream in = pageContext.getServletContext().getResourceAsStream(src); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String str = null; while((str = reader.readLine()) != null) { Pattern.compile("<").matcher(str).replaceAll("<"); Pattern.compile(">").matcher(str).replaceAll(">"); pageContext.getOut().write(str); pageContext.getOut().write("<br>"); } } } <tag> <name>readerFile</name> <tag-class>com.atguigu.javaweb.tag.ReadFuleTag</tag-class> <body-content>empty</body-content> <attribute> <name>src</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> <atguigu:readerFile src="/WEB-INF/note.txt"/>
1.带标签体的自定义标签
1》若一个标签有标签体:
<atguigu:testJspFragment>HelloWorld</atguigu:testJspFragment>
在自定义标签处理器中使用JspFragment对象封装标签体信息
2》若配置标签韩有标签体,则JSP引擎会调用setJspBody()方法 把 JspFragment 传递给标签处理器类
在SimpleTagSupport 中还定义了一个getJspBody() 方法,用于返回JspFragment 对象
3》JspFragment 的invoke(Writer)方法:把标签体内容重Writer中输出,若为null,则等同于invoke(getJspContext().getOut()),及直接把标签体内容输出到页面上
有时可以借助StringWriter,先得到标签体的内容
//1.使用StringWriter得到标签体的内容
StringWriter sw = new StringWriter();
bodyContent.invoke(sw);
//2.把标签体的内容都变成大写
String content = sw.toString().toUpperCase();
//3.获取页面上隐含的out隐含对象输出到页面上
//System.out.println(sw.toString());
getJspContext().getOut().print(content);
4》在tld文件中,使用body-content节点来描述标签体的类型:
<body-content>:指定标签体的类型。可能取值的三种 大部分情况下取值scriptless
empty:没有标签体
scriptless:标签体可以包含el表达式和JSP动作元素,但不可以包含JSP的脚本元素
tagdependent:标签体交由本身解析处理。指定tagdependent,在标签体中的所有代码都会原封不动的交由标签体处理,而不是执行结果较有标签体处理
<body-content>scriptless</body-content>
5>定义一个自定义标签:
<atguigu:printUpper time="10">asdf</atguigu>
把标签体内容转化为大写并输出time次到浏览器
6>实现foreach标签:
》两个属性:items(集合类型,Colllection),var(String 类型)
》doTag:
*遍历items对应的集合,
*把正在遍历的对象放入pageContext中,键:var,值;正在遍历的对象
*把标签体的内容直接输出到页面上
<c:forEach items="${requestScope.customers }" var="cust">
${pageScope.cust.id }--${cust.name }--<br>
</c:forEach>
2.开发有父标签的标签:
父标签无法获取子标签的引用,父标签仅把子标签作为标签体来使用
子标签可以通过getParent()方法来获取父标签的引用(需继承 SimplieTagSupport 或自实现SimplieTag接口的该方法)
若子标签的确有父标签,JSP引擎会把代表父标签的引用通过 setParent(JspTag parent)赋给标签处理器 。该标签是一个空接口 但是来统一SimpleTag 和 Tag的。实际使用需要类型的强制转换
在tld配置文件中,无需为父标签用额外的配置。但子标签是以标签体的形式存在的,所以父标签的<body-content></body-content>需要设置为scriptless
注意:父标签的类型是JspTag类型
实现:
<c:choose>
<c:when test="${param.age > 24}">大学毕业</c:when>
<c:when test="${param.age > 20}">高中毕业</c:when>
<c:otherwise>高中以下。。。</c:otherwise>
</c:choose>
开发标签3个:choose,when,otherwise
其中when标签有一个boolean类型的属性:test
choose是when 和 otherwise的标签的父标签, when 在otherwise 之前使用
在父标签choose中定义一个“全局” 的boolean类型的flag:用于判断子标签在满足条件下是否执行
*若when的test为true,且when的父标签的flag也为true,则执行when的标签体(正常输出标签体的内容),
同时把flag设置为false
*若when的test为true,且when的父标签的flag也为false,则不执行标签体
*若flag为true,otherwise执行标签体

浙公网安备 33010602011771号