900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 自定义标签的详细使用讲解【上】

自定义标签的详细使用讲解【上】

时间:2024-01-23 20:40:45

相关推荐

自定义标签的详细使用讲解【上】

目录

一、前言

1.什么是自定义标签

2.自定义标签的两种类型

3.为什么要使用自定义标签

4.使用场景

二、自定义标签的使用

1自定义标签的生命周期

2.创建自定义标签

2.1.编写助手类

2.2.编写标签库的tld文件

2.3.jsp页面引用标签

2.4.总结

三、解析自定义标签

1.为什么要重写doStartTag方法?

2.自定义标签的工作流程

四、案例

1.模拟c标签中if标签

2.模拟c标签中的foreach标签

一、前言

1.什么是自定义标签

在了解什么是自定义标签之前,我们先了解什么是标签。

标签(Tag):是一种特殊的语言构造,通常用于在一些具有特定功能的语言中指定标记或元数据,从而实现一些特殊的效果或功能。很多与“ML”结尾的语言都是标记语言,比如:HTML,XML,XHTML,VML等等。标记语言与其他语言一样,也需要运行它们的环境,比如HTML的运行环境时浏览器,XML也要自己的解析和运行的环境。

自定义标签(Custom Tag):是指在JSP中,开发者自行定义的可扩展标记(Tag),用于扩展和增强JSP的功能。可以使用自定义标签可以实现一些自定义逻辑,如访问Web服务、执行数据库操作、生成HTML代码、进行数据处理等复杂操作;还可以实现基于标签的流程控制、数据模型、动态样式等功能。

2.自定义标签的两种类型

简单标签

指不包含主体内容的标签,简单标签的处理一般是基于标签的属性和参数,例如<br>、<hr>

标签体标签

是指包含主体内容的标签,标签体标签的处理需要对标签的主体内容进行解析和处理,例如<if>标签和<foreach>标签等。

3.为什么要使用自定义标签

1.易于维护和重用

自定义标签将复杂的逻辑封装在单一的标签中。这使得代码更易于维护和重用,可以将一些常用的逻辑封装在标签中,避免代码重复和冗余。

2.提高代码的可读性

通过使用自定义标签,可以将业务逻辑和代码标签化,从而提高代码的可读性和可维护性。标签化的代码更符合人类的思维模式,理解和调试也更为方便。

3.分离业务和呈现逻辑

使用自定义标签可以分离业务逻辑和呈现逻辑,帮助开发者更好地实现MVC(Model-View-Controller)设计模式,提高应用程序的可扩展性和重用性。

4.提高应用程序的性能

使用自定义标签可以将需要多次重复执行的代码封装在标签中,从而减少代码重复和冗余,提高应用程序的性能。

4.使用场景

我们在做Web项目的时候,肯定是多人开发,但是有很多的代码是相同的,为了减少代码冗余,我们就可以自定义标签,共大家使用,提高效率也方便维护。

二、自定义标签的使用

1自定义标签的生命周期

由图可知我们大致分为四个阶段

实例化阶段、初始化阶段、使用阶段和实例释放阶段

2.创建自定义标签

看图很难理解,所以我们接下来直接上代码。

模拟c标签中的out标签

2.1.编写助手类

package c;import java.io.IOException;import javax.servlet.jsp.JspWriter;import javax.servlet.jsp.tagext.BodyTagSupport;/*** 自定义标签继承BodyTagSupport 作用:用于在jsp页面输出内容* * @author Java方文山**/public class OutTag extends BodyTagSupport {private String val;// out标签需要输出的属性值private String defaultVal;// out标签默认输出属性值public void setVal(String val) {this.val = val;}public void setDefaultVal(String defaultVal) {this.defaultVal = defaultVal;}// 重写doStartTag方法@Overridepublic int doStartTag() {// 因为要在页面输出内容,所以先获取out对象JspWriter out = this.pageContext.getOut();try {// 判断标签属性有无值if (this.val == null || "".equals(this.val)) {// 标签属性为空输出默认值out.print(this.defaultVal);} else {// 标签属性不为空输出标签属性值out.print(this.val);}} catch (IOException e) {e.printStackTrace();}// 跳过主体return SKIP_BODY;/** SKIP_BODY以后最后用这种写法来写(成员变量), 不然别的程序员看不懂你写的代码,利用成员变量更加理解以及维护代码。* */}}

2.2.编写标签库的tld文件

<!DOCTYPE taglibPUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN""/dtd/web-jsptaglibrary_1_2.dtd"><!-- 标签库描述符 --><taglib xmlns="/JSP/TagLibraryDescriptor"><tlib-version>1.0</tlib-version><jsp-version>1.2</jsp-version><short-name>Simple Tags</short-name><!--引用自定义标签的uri路径--><uri>/xw</uri><tag><!-- 标签名 --><name>out</name><!-- 标签助手类 --><tag-class>c.OutTag</tag-class><!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 --><body-content>empty</body-content><attribute><!-- 属性名, OutTag类中的val属性相匹配 --><name>val</name><!-- 表示该属性是否为必要的属性 --><required>true</required><!-- 该属性是否可以接受EL表示式的值 --><rtexprvalue>true</rtexprvalue><!-- 标签描述,用于说明标签的作用 --><description>out标签val属性,用于输出val的值</description></attribute><attribute><!-- 属性名, OutTag类中的defaultVal属性相匹配 --><name>defaultVal</name><!-- 表示该属性为必要的属性 --><required>false</required><!-- 该属性可以接受EL表示式的值 --><rtexprvalue>false</rtexprvalue><!-- 标签描述,用于说明标签的作用 --><description>out标签,如val属性值为空,则输出该默认值</description></attribute></tag></taglib>

2.3.jsp页面引用标签

<%@page import="c.TestForeach"%><%@page import="c.Student"%><%@page import="java.util.List"%><%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><!-- 引入自定义标签--><%@taglib prefix="xw" uri="/xw" %><!DOCTYPE><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>自定义标签</title></head><body><!--自定义out标签输出 --><xw:out val="你好我是自定义标签out,val属性输出"/><br><!--自定义out标签EL表达式使用 --><%request.setAttribute("name", "我是在作用域的文件,利用EL表达式获取");%><xw:out val="${name }"/><br><!--自定义out标签defaultVal属性输出 --><%request.setAttribute("x", null);%><xw:out val="${x}" defaultVal="我是out标签的默认值输出1"/><xw:out val="" defaultVal="我是out标签的默认值输出2"/><br><hr></body></html></body></html>

浏览器输出结果

2.4.总结

由上可知,我们自定义标签只需要三步,①编写助手类②编写tld文件③页面引入自定义。

①编写助手类:编写一个普通的Java类继承BodyTagSupport类,为什么这里是继承类而不是是实现接口,因为BodyTagSupport类里的功能,开发人员可能不需要,实现接口就必须重写方法,可能会出错,而继承则是开发人员重写自己所需要的方法即可。在助手类里面定义自定义标签所需的属性,并编写set方法(后期需要通过反射往实例里面插入值)。重写doStartTag方法,并加上@Override注解。

②编写tld文件:tld文件可变内容就是<tag>里的元素,其他内容“cv”操作即可,自定义标签的属性名字必须和助手类一致,而且自定义标签的助手类路径名必须是正确的全路径名

③页面引入自定义:直接在需要自定义标签的地方<%@taglib prefix="xw" uri="/xw" %>引用即可,uri就是自己在tld文件所写的。

三、解析自定义标签

1.为什么要重写doStartTag方法?

在自定义标签处理器中,doStartTag()方法是必须要实现的,因为它是JSP引擎在解析页面时调用的第一个方法,并且用于处理标签的开始标记。

如果不重写doStartTag()方法,那么JSP引擎会默认返回 SKIP_BODY 的值,也就是说,页面在遇到自定义标签时,标签体内的所有内容都将被略过不被执行。

2.自定义标签的工作流程

编译器看不懂“jsp文件”,它会先转成java文件,然后先通过jsp页面的引用自定义标签路径,找到tld文件,然后通过找到使用<tag>编写的标签找到指定的<tag-class>,通过里面的全路径名反射实例(助手类)调用doStartTag方法对标签进行处理。

四、案例

1.模拟c标签中if标签

编写助手类

package c;import javax.servlet.jsp.tagext.BodyTagSupport;/**自定义标签继承BodyTagSupport 作用:用于jsp页面进行if判断* @author Java方文山**/public class IfTag extends BodyTagSupport{private boolean test;//if标签的比较值属性public void setTest(boolean test) {this.test = test;}//重写doStartTag方法@Overridepublic int doStartTag() {//判断传进来的的值是不是trueif(this.test) {//是true输出主体内容return EVAL_BODY_INCLUDE;}//是false跳过主体内容return SKIP_BODY;}}

编写tld文件

<!DOCTYPE taglibPUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN""/dtd/web-jsptaglibrary_1_2.dtd"><!-- 标签库描述符 --><taglib xmlns="/JSP/TagLibraryDescriptor"><tlib-version>1.0</tlib-version><jsp-version>1.2</jsp-version><short-name>Simple Tags</short-name><uri>/xw</uri><tag><!-- 标签名 --><name>if</name><!-- 标签助手类 --><tag-class>c.IfTag</tag-class><!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 --><body-content>jsp</body-content><attribute><!-- 属性名, OutTag类中的val属性相匹配 --><name>test</name><!-- 表示该属性是否为必要的属性 --><required>true</required><!-- 该属性是否可以接受EL表示式的值 --><rtexprvalue>true</rtexprvalue><!-- 标签描述,用于说明标签的作用 --><description>if标签test属性,用于比较该属性的内容是否一致,如果一致则输出主体内容,不一致不输出</description></attribute></tag></taglib>

页面引入标签

<%@page import="c.TestForeach"%><%@page import="c.Student"%><%@page import="java.util.List"%><%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@taglib prefix="xw" uri="/xw" %><!DOCTYPE><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>自定义标签</title></head><body><!--自定义out标签输出 --><xw:out val="你好我是自定义标签out,val属性输出"/><br><!--自定义out标签EL表达式使用 --><%request.setAttribute("name", "我是在作用域的文件,利用EL表达式获取");%><xw:out val="${name }"/><br><!--自定义out标签defaultVal属性输出 --><%request.setAttribute("x", null);%><xw:out val="${x}" defaultVal="我是out标签的默认值输出1"/><xw:out val="" defaultVal="我是out标签的默认值输出2"/><br><hr><!-------------------------------------------------------------------------------------><!--自定义if标签 --><xw:if test="${1==1 }">if判断成立,主体内容输出</xw:if><xw:if test="${1==2 }">if判断成立,主体内容输出</xw:if><hr></body></html></body></html>

浏览器显示结果

2.模拟c标签中的foreach标签

编写助手类

package c;import java.util.Iterator;import java.util.List;import java.util.Objects;import javax.servlet.jsp.tagext.BodyTagSupport;/*** 自定义标签继承BodyTagSupport 作用:用于jsp页面进行对集合进行遍历输出* * @author Java方文山**/public class ForeachTag extends BodyTagSupport {private List<Object> items;// 存放数据源private String var;// 利用El表达式取出该对象的属性,域对象保存数据源的值public void setItems(List<Object> items) {this.items = items;}public void setVar(String var) {this.var = var;}//重写doStartTag方法@Overridepublic int doStartTag() {//判断数据源是否有数据if(this.items.size()==0 ||Objects.isNull(this.items)) {//数据源为空跳过主体return SKIP_BODY;}//将数据源转换为迭代器Iterator<Object> iterator = this.items.iterator();//将数据源中的下一个返回Object next = iterator.next();//将刚刚拿到的值赋值给pageContext域对象并取值为varthis.pageContext.setAttribute(var, next);//将迭代器也存入域对象并继续计算主体this.pageContext.setAttribute("iterator", iterator);//计算主体内容然后输出return EVAL_BODY_INCLUDE;}//重写doAfterBody方法,对数据源的数据进行迭代读取处理@Overridepublic int doAfterBody() {//拿到域对象保存的迭代器Iterator<Object> ite = (Iterator<Object>) this.pageContext.getAttribute("iterator");//判断迭代器对象的下一个有没有值if(ite.hasNext()) {//有值,继续放入pageContext域对象并取值为varthis.pageContext.setAttribute("var", ite.next());//再次计算主体return EVAL_BODY_AGAIN;}//迭代器下一个没有值直接跳过主体return SKIP_BODY;}}

编写tld文件

<!DOCTYPE taglibPUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN""/dtd/web-jsptaglibrary_1_2.dtd"><!-- 标签库描述符 --><taglib xmlns="/JSP/TagLibraryDescriptor"><tlib-version>1.0</tlib-version><jsp-version>1.2</jsp-version><short-name>Simple Tags</short-name><uri>/xw</uri><tag><!-- 标签名 --><name>foreach</name><!-- 标签助手类 --><tag-class>c.ForeachTag</tag-class><!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 --><body-content>jsp</body-content><attribute><!-- 属性名, OutTag类中的val属性相匹配 --><name>items</name><!-- 表示该属性是否为必要的属性 --><required>true</required><!-- 该属性是否可以接受EL表示式的值 --><rtexprvalue>true</rtexprvalue><!-- 标签描述,用于说明标签的作用 --><description>foreach标签items属性,用于保存数据源</description></attribute><attribute><!-- 属性名, OutTag类中的val属性相匹配 --><name>var</name><!-- 表示该属性是否为必要的属性 --><required>true</required><!-- 该属性是否可以接受EL表示式的值 --><rtexprvalue>true</rtexprvalue><!-- 标签描述,用于说明标签的作用 --><description>foreach标签var属性,用于保存数据源的值,以便于el表达式获取内容</description></attribute></tag></taglib>

编写模拟实体类和初始化数据类

package c;/*** 用于测试自定义标签foreach* * @author Java方文山**/public class Student {private int sid;private String sname;public Student() {// TODO Auto-generated constructor stub}public Student(int sid, String sname) {super();this.sid = sid;this.sname = sname;}public int getSid() {return sid;}public void setSid(int sid) {this.sid = sid;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}}

package c;import java.util.ArrayList;import java.util.List;/*** 初始化Student数据* * @author Java方文山**/public class TestForeach {public static List<Student> AddStudent() {List<Student> list = new ArrayList<Student>();Student s1 = new Student(1, "xw");Student s2 = new Student(2, "wh");Student s3 = new Student(3, "sb");list.add(s1);list.add(s2);list.add(s3);return list;}}

页面引用标签

<%@page import="c.TestForeach"%><%@page import="c.Student"%><%@page import="java.util.List"%><%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@taglib prefix="xw" uri="/xw" %><!DOCTYPE><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>自定义标签</title></head><body><!--自定义out标签输出 --><xw:out val="你好我是自定义标签out,val属性输出"/><br><!--自定义out标签EL表达式使用 --><%request.setAttribute("name", "我是在作用域的文件,利用EL表达式获取");%><xw:out val="${name }"/><br><!--自定义out标签defaultVal属性输出 --><%request.setAttribute("x", null);%><xw:out val="${x}" defaultVal="我是out标签的默认值输出1"/><xw:out val="" defaultVal="我是out标签的默认值输出2"/><br><hr><!-------------------------------------------------------------------------------------><!--自定义if标签 --><xw:if test="${1==1 }">if判断成立,主体内容输出</xw:if><xw:if test="${1==2 }">if判断成立,主体内容输出</xw:if><hr><!-------------------------------------------------------------------------------------><!--自定义foreach标签 --><%//测试数据List<Student> stu=TestForeach.AddStudent();//将数据保存在request对象中request.setAttribute("stu", stu);%><xw:foreach items="${stu }" var="stu"><xw:out val="${stu.sid }"/><xw:out val="${stu.sname }"/></xw:foreach></body></html></body></html>

浏览器显示结果

至此这篇自定义标签就讲解到这里,如果有不足之处欢迎评论区留言讨论!!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。