jsp 自定义标签
传统方式
https://www.cnblogs.com/xdouby/p/7929749.html
(1)自定义标签
传统方式:实现Tag接口 jsp1.1
int doStartTag() throws JspException;
简单方式:实现SimpleTag接口 jsp2.0
void doTag() throws JspException, IOException;
(2)步骤
- 编写标签处理类
如果jsp在编译阶段发现了自定义标签xx:,就会交给doStartTag()或者 doTag()
- 编写标签描述符
tld (tag library description)
建议编写:可以仿照其他标签语言(el jstl)的tld文件
<body-content>的值有下面4种:
<xsd:enumeration value="tagdependent"/>
<xsd:enumeration value="JSP"/>
<xsd:enumeration value="empty"/>
<xsd:enumeration value="scriptless"/>
tagdependent:标签体内容直接被写入BodyContent,由自定义标签类来进行处理,而不被JSP容器解释,
如下:
<test:myList>
select name,age from users
</test:myList>
JSP:接受所有JSP语法,如定制的或内部的tag、scripts、静态HTML、脚本元素、JSP指令和动作。如:
<my:test>
<%=request.getProtocol()%> // ②
</my:test>
具体可参考后面附源码。
empty:空标记,即起始标记和结束标记之间没有内容。
下面几种写法都是有效的,
<test:mytag />
<test:mytag uname="Tom" />
<test:mytag></test:mytag>
scriptless:接受文本、EL和JSP动作。如上述②使用<body-content> scriptless </body-content>则报错,具体可参考后面附源码。除了<% %> <%! %> <%= %>意外的的jsp元素
- 导入并使用
tld文件应放在WEB-INF或其子目录下面
引入具体的tld文件
uri:定位文件
prefix:前缀,代表文件名
<%@taglib prefix="" uri="" %>
(3)Tag
int doStartTag() throws JspException;
该方法有两个返回值
int SKIP_BODY = 0; 标签体不会被执行
int EVAL_BODY_INCLUDE = 1; 标签体会被执行
int doEndTag() throws JspException;
int SKIP_PAGE = 5; 标签体后的jsp不会被执行
int EVAL_PAGE = 6; 标签体后的jsp会被执行
jsp—servlet:当jsp容器将jsp翻译成.servlet的时候,如果遇到jsp中有标签,就会依次执行setPageContext setParent doStartTag doEndTag release用于解析标签的执行逻辑。
IterationTag
http://tomcat.apache.org/tomcat-5.5-doc/jspapi/javax/servlet/jsp/tagext/IterationTag.html
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JJItDEL6-1624196601074)(http://tomcat.apache.org/tomcat-5.5-doc/jspapi/javax/servlet/jsp/tagext/doc-files/IterationTagProtocol.gif)]
(4)实现
遍历三次
package com.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
public class MyIteration extends TagSupport {
//决定重复次数
private int num;
public void setNum(int num) {
this.num = num;
}
// 执行标签
@Override
public int doStartTag() throws JspException {
// 先执行标签体一次
return EVAL_BODY_INCLUDE;
}
// 执行标签后
@Override
public int doAfterBody() throws JspException {
num--;
// 再重复执行一次
return num > 0 ? EVAL_BODY_AGAIN : SKIP_BODY;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--标签库的头文件-->
<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">
<!--描述-->
<description>迭代器标签库</description>
<!--版本-->
<tlib-version>1.0</tlib-version>
<!--简称-->
<short-name>mytaglib</short-name>
<!--全称-->
<!--<display-name>MyTagLibrary</display-name>-->
<!--定位标签库-->
<uri>http://www.zrm.com</uri>
<!--自定义标签的相关信息-->
<tag>
<!--标签的描述-->
<description>迭代器标签</description>
<!--标签名-->
<name>iteration3</name>
<!--标签处理类-->
<tag-class>com.tag.MyIteration</tag-class>
<!--标签体的类型-->
<body-content>JSP</body-content>
<attribute>
<name>num</name>
<required>true</required>
</attribute>
</tag>
</taglib>
<%@taglib prefix="zrm" uri="http://www.zrm.com" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>循环三次</title>
</head>
<body>
<zrm:iteration3 num="3">
hello
</zrm:iteration3>
</body>
</html>
(5)BodyTag
如果在标签体显示之前,进行一些额外的操作
查看实现类:Ctrl alt B
int EVAL_BODY_BUFFERED = 2;
是doStartTag()的第三个返回值,代表一个缓冲区
void setBodyContent(BodyContent var1);
如果返回值是EVAL_BODY_BUFFERED,则服务器会自动将标签需要显示的内容放入缓冲区(BodyContent)
BodyContent
获得缓存区数据
public abstract Reader getReader();
public abstract String getString();
输出
public abstract void writeOut(Writer var1) throws IOException;
public JspWriter getEnclosingWriter() {
return this.enclosingWriter;
}
(6)处理流程
(7)转换大写
- 编写标签类
package com.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.io.IOException;
public class ToUpperCase extends BodyTagSupport {
// 1.告诉程序将原来的hello 变成大写(父类已完成)
// 将doStartTag()的返回值变成EVAL_BODY_BUFFERED才可修改
// 2.获取数据修改
@Override
public int doEndTag() throws JspException {
try {
// 拿到缓冲区的数据
String content = getBodyContent().getString();
// 修改
content = content.toUpperCase();
// 输出
bodyContent.getEnclosingWriter().write(content);
} catch (IOException e) {
e.printStackTrace();
}
// 默认为6,标签执行完成后继续执行后面的jsp元素
return super.doEndTag();
}
}
<tag>
<name>toUpperCase</name>
<tag-class>com.tag.ToUpperCase</tag-class>
<body-content>JSP</body-content>
</tag>
<zrm:toUpperCase>
hello
</zrm:toUpperCase>
简单方式
修改文本通过流
SimpleTag
void doTag() throws JspException, IOException;
集成了传统方式的三个方法
代表一个jsp片段,但是不包含scriptless,由此简单方式的tld文件中 <body-content> 不能是JSP
package javax.servlet.jsp.tagext.JspFragment;
如果要修改显示内容,则要修改此流,调用一次invoke则执行一次标签体
public abstract void invoke(Writer var1) throws JspException, IOException;
获取对象JspFragment
protected JspFragment getJspBody() {
return this.jspBody;
}
package com.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
public class MySimpleTagIterator extends SimpleTagSupport {
private int num;
public void setNum(int num) {
this.num = num;
}
@Override
public void doTag() throws JspException, IOException {
JspFragment jspBody = getJspBody();
for (int i = 0; i < num; i++) {
jspBody.invoke(null);
}
super.doTag();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--标签库的头文件-->
<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">
<!--描述-->
<description>简单迭代器标签库</description>
<!--版本-->
<tlib-version>1.0</tlib-version>
<!--简称-->
<short-name>mysimpletaglib</short-name>
<!--全称-->
<!--<display-name>MyTagLibrary</display-name>-->
<!--定位标签库-->
<uri>http://www.zrmsimple.com</uri>
<!--自定义标签的相关信息-->
<tag>
<!--标签的描述-->
<description>简单迭代器标签</description>
<!--标签名-->
<name>mySimpleTagIterator</name>
<!--标签处理类-->
<tag-class>com.tag.MySimpleTagIterator</tag-class>
<!--标签体的类型-->
<body-content>scriptless</body-content>
<attribute>
<name>num</name>
<required>true</required>
</attribute>
</tag>
</taglib>
<zrmsimple:mySimpleTagIterator num="3">
zrm
</zrmsimple:mySimpleTagIterator>