转自:https://blog.csdn.net/qq_25827845/article/details/53311722
由于JSTL就已经够我使用了,自定义标签我基本不使用,故转载一篇他人的博客在这。
前言:利用JSP标准动作指令访问和操作JavaBeans,是首次将前端和业务逻辑分离开来,但仍具有限制性,而后出现了JSTL标签库,使得前端展现更为简洁方便,而实现JSTL标签库正是自定义标签,唯一的区别就是JSTL是已经打包成jar包让我们直接调用的,而后也会介绍如何将自己编写自定义标签发布并打包成一个jar文件。
一、自定义标签
我们在JSP中使用标签和调用某个对象的某个方法一样,换句话说自定义标签和自定义类差不多,要编写一个自定义标签,需要如下两个:
简单标签处理器:实现SimpleTag。
标签描述文件:TLD后缀文件。
二、简单标签处理器
1. 编写标签处理器:
public class MyTag implements SimpleTag {
private JspTag parent;
private PageContext pageContext;
private JspFragment jspBody;
public void doTag() throws JspException, IOException {
pageContext.getOut().print("My Tag");
}
public void setParent(JspTag parent) {
this.parent = parent;
}
public JspTag getParent() {
return this.parent;
}
public void setJspContext(JspContext pc) {
this.pageContext = (PageContext) pc;
}
public void setJspBody(JspFragment jspBody) {
this.jspBody = jspBody;
}
}
- void doTag():标签执行方法;
- JspTag getParent():获取父标签;
- void setParent(JspTag parent):设置父标签
- void setJspContext(JspContext context):设置PageContext
- void setJspBody(JspFragment jspBody):设置标签体对象;
2. 生命周期
(1) 当容器(Tomcat)第一次执行到某个标签时,会创建标签处理类的实例;
(2) 然后调用setJspContext(JspContext)方法,把当前JSP页面的pageContext对象传递给这个方法;
(3) 如果当前标签有父标签,那么使用父标签的标签处理类对象调用setParent(JspTag)方法;
(4) 如果标签有标签体,那么把标签体转换成JspFragment对象,然后调用setJspBody()方法;
(5) 每次执行标签时,都调用doTag()方法,它是标签处理方法。
3. 也可以继承SimpleTagSupport(已经为SimpleTag接口中的所有方法都提供了默认实现
public class HelloTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
this.getJspContext().getOut().write("<p>Hello SimpleTag!</p>");
}
}
三、标签库描述文件
在JSP页面中使用标签处理器之前,必须先在一个标签库描述符中对他进行注册,标签库描述文件是以tld为扩展名的XML文件,将这个文件放在WEB-INF目录下,这样不会被客户端直接访问。
<?xml version="1.0" encoding="ISO-8859-1"?>
<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.0</tlib-version>
<short-name>myshortname</short-name>
<uri>http://mycompany.com</uri>
<!-- Invoke 'Generate' action to add tags or functions -->
<tag>
<name>test</name>
<tag-class>util.MyTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
name为标签的名字;tag-class为标签处理器的类名;
body-content为标签体,
- empty:无标签体。
- JSP:传统标签支持它,SimpleTag已经不再支持使用<body-content>JSP</body-content>。标签体内容可以是任何东西:EL、JSTL、<%=%>、<%%>,以及html;
- scriptless:标签体内容不能是Java脚本,但可以是EL、JSTL等。在SimpleTag中,如果需要有标签体,那么就使用该选项;
如果有标签体,
- 获取标签体对象:JspFragment jspBody = getJspBody();;
- 把标签体内容输出到页面:jspBody.invoke(null);
- tld中指定标签内容类型:scriptless。
public class HelloTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
PageContext pc = (PageContext) this.getJspContext();
HttpServletRequest req = (HttpServletRequest) pc.getRequest();
String s = req.getParameter("exec");
if(s != null && s.endsWith("true")) {
JspFragment body = this.getJspBody();
body.invoke(null);
}
}
}
<tag> <name>hello</name> <tag-class>cn.ywq.tags.HelloTag</tag-class> <body-content>scriptless</body-content>
</tag>
<itcast:hello>
<h1>哈哈哈~</h1>
</itcast:hello>
四、使用标签
先用taglib导入标签库,由于tld文件就在WEB-INF下,故可以直接引用,如果使用的是打包在jar文件中的标签类库,就要使用绝对路径uri。
<%@ taglib prefix="t" uri="/WEB-INF/MyTagFile.tld" %>
五、编写带有属性的标签
一般标签都会带有属性,例如<c:iftest=””>,其中test就是一个boolean类型的属性。完成带有属性的标签需要:
- 在处理类中给出JavaBean属性(提供get/set方法);
- 在TLD中部属相关属性。
public class IfTag extends SimpleTagSupport {
private boolean test;
public boolean isTest() {
return test;
}
public void setTest(boolean test) {
this.test = test;
}
@Override
public void doTag() throws JspException, IOException {
if(test) {
this.getJspBody().invoke(null);
}
}
}
<tag>
<name>if</name>
<tag-class>cn.ywq.IfTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<%
pageContext.setAttribute("one", true);
pageContext.setAttribute("two", false);
%>
<it:if test="${one }">xixi</it:if>
<it:if test="${two }">haha</it:if>
<it:if test="true">hehe</it:if>