素材巴巴 > 程序开发 >

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

程序开发 2023-09-14 22:11:54

目录

一、前言

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.自定义标签的两种类型

简单标签

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


标签体标签

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

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文件


 
 1.01.2Simple Tags
 /xwoutc.OutTagemptyvaltruetrueout标签val属性,用于输出val的值defaultValfalsefalseout标签,如val属性值为空,则输出该默认值
 

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" %>
 
 
 
 
 自定义标签
 
 
 
 
<% request.setAttribute("name", "我是在作用域的文件,利用EL表达式获取"); %>
<% request.setAttribute("x", null); %>

浏览器输出结果

 2.4.总结

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

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

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

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

三、解析自定义标签

助手类里的return值 返回值含义SKIP_BODY跳过主体EVAL_BODY_INCLUDE计算标签主体内容并输出EVAL_BODY_AGAIN再次计算主体一次EVAL_PAGE计算页面的后续部分SKIP_PAGE跳过页面的后续部分

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

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

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

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

编译器看不懂“jsp文件”,它会先转成java文件,然后先通过jsp页面的引用自定义标签路径,找到tld文件,然后通过找到使用编写的标签找到指定的,通过里面的全路径名反射实例(助手类)调用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文件


 
 1.01.2Simple Tags/xwifc.IfTagjsptesttruetrueif标签test属性,用于比较该属性的内容是否一致,如果一致则输出主体内容,不一致不输出
 

页面引入标签

<%@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" %>
 
 
 
 
 自定义标签
 
 
 
 
<% request.setAttribute("name", "我是在作用域的文件,利用EL表达式获取"); %>
<% request.setAttribute("x", null); %>

if判断成立,主体内容输出 if判断成立,主体内容输出

浏览器显示结果

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 items;// 存放数据源private String var;// 利用El表达式取出该对象的属性,域对象保存数据源的值public void setItems(List 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 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 ite = (Iterator) this.pageContext.getAttribute("iterator");//判断迭代器对象的下一个有没有值if(ite.hasNext()) {//有值,继续放入pageContext域对象并取值为varthis.pageContext.setAttribute("var", ite.next());//再次计算主体return EVAL_BODY_AGAIN;}//迭代器下一个没有值直接跳过主体return SKIP_BODY;}}
  
 

编写tld文件


 
 1.01.2Simple Tags/xwforeachc.ForeachTagjspitemstruetrueforeach标签items属性,用于保存数据源vartruetrueforeach标签var属性,用于保存数据源的值,以便于el表达式获取内容
 

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

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 AddStudent() {List list = new ArrayList();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" %>
 
 
 
 
 自定义标签
 
 
 
 
<% request.setAttribute("name", "我是在作用域的文件,利用EL表达式获取"); %>
<% request.setAttribute("x", null); %>

if判断成立,主体内容输出 if判断成立,主体内容输出
<% //测试数据 List stu=TestForeach.AddStudent(); //将数据保存在request对象中 request.setAttribute("stu", stu); %>

浏览器显示结果

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


标签:

上一篇: (24):vue的理解 下一篇:
素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。