由自定义标签了解标签是如何起作用的
标签配置文件 tld
talk is cheap show me the code:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<!-- 标签库的版本号 -->
<tlib-version>1.2</tlib-version>
<!-- 标签库的简写名称 -->
<short-name>mytag</short-name>
<!-- 标签库对应的唯一uri -->
<uri>http://heyahui/taglib</uri>
<!-- 自定义的标签 -->
<tag>
<!-- 标签名称 -->
<name>hello</name>
<!-- 实现标签功能的类的具体路径 -->
<tag-class>a_tag.HelloTag</tag-class>
<!-- 标签体内容的限制 scriptless:不支持jsp empty:内容为空 tagdependent:支持jsp,但当作文本 JSP:支持jsp,不建议 -->
<body-content>scriptless</body-content>
<!-- 标签中的属性 -->
<attribute>
<!-- 属性的名字 -->
<name>num</name>
<!-- 属性是否是必须的 -->
<required>false</required>
<!-- 属性是否支持EL表达式 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>
有了这个配置文件,我们下面只需要一个类来实现标签的具体功能就行了
标签的实现类
talk is cheap show me the code:
package a_tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class HelloTag extends SimpleTagSupport {
// 标签属性的具体实现
private int num;
// 标签属性的获取方法
public void setNum(int num) {
this.num = num;
}
@Override
// 该方法是用于标签的具体功能实现的
public void doTag() throws JspException, IOException {
// 输出标签中的内容但无法对内容修改
this.getJspBody().invoke(null);
// 获取标签的内容并修改后输出
JspFragment jspBody = this.getJspBody();
StringWriter writer = new StringWriter();
jspBody.invoke(writer);
String content = writer.toString();
content = content.subString(0,1);
this.getContext().getOut().write(content);
/*
*这里讲一下直接输出的原理
*invoke()方法的参数为null时其实是默认将JspWriter作为其对象的,并调用它的write()方法
*直接将标签内容传给页面的输出流,我们无法做修改
*要想修改这个内容,必须用一个其它流去接收它,然后再做修改
*/
}
}
上面的代码省略了一些标签类的其它方法,这些方法主要是用于标签的具体创建等生命周期的,都在超类中进行了重写,所以我们一般只需要重写具体的逻辑即可
案例参考
这里,我们来模仿几个主流的标签的实现
talk is cheap show me the code
if 标签
<!-- tld文件中的标签部分 -->
<!-- if -->
<tag>
<name>if</name>
<tag-class>a_tag.IfTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
package a_tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class IfTag extends SimpleTagSupport {
private boolean test;
public void setTest(boolean test) {
this.test = test;
}
@Override
public void doTag() throws JspException, IOException {
if (testValue) {
this.getJspBody().invoke(null);
}
}
}
choose 标签
<!-- tld文件中的标签部分 -->
<!-- choose -->
<tag>
<name>choose</name>
<tag-class>a_tag.ChooseTag</tag-class>
<body-content>scriptless</body-content>
</tag>
<!-- when -->
<tag>
<name>when</name>
<tag-class>a_tag.WhenTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<!-- otherwise -->
<tag>
<name>otherwise</name>
<tag-class>a_tag.OtherwiseTag</tag-class>
<body-content>scriptless</body-content>
</tag>
package a_tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class ChooseTag extends SimpleTagSupport {
private boolean flag;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void doTag() throws JspException, IOException {
this.getJspBody().invoke(null);
}
}
package a_tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class WhenTag extends SimpleTagSupport {
private boolean test;
public void setTest(boolean test) {
this.test = test;
}
@Override
public void doTag() throws JspException, IOException {
if (test) {
this.getJspBody().invoke(null);
}
((ChooseTag) this.getParent()).setFlag(test);
}
}
package a_tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class OtherwiseTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
if (!((ChooseTag) this.getParent()).isFlag()) {
this.getJspBody().invoke(null);
}
}
}
foreach标签
<!-- tld文件中的标签部分 -->
<!-- foreach -->
<tag>
<name>foreach</name>
<tag-class>a_tag.ForeachTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
package a_tag;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class ForeachTag extends SimpleTagSupport {
private Object items;
private String var;
public void setItems(Object items) {
this.items = items;
}
public void setVar(String var) {
this.var = var;
}
@Override
public void doTag() throws JspException, IOException {
PageContext context = (PageContext) this.getJspContext();
if (items instanceof List) {
List list = (List) items;
for (Object object : list) {
context.setAttribute(var, object);
this.getJspBody().invoke(null);
}
} else if (items instanceof Map) {
Map<String, Object> map = (Map) items;
for (Map.Entry entry : map.entrySet()) {
context.setAttribute(var, entry);
this.getJspBody().invoke(null);
}
}
}
}