🥳🥳Welcome Huihui's Code World ! !🥳🥳
接下来看看由辉辉所写的关于自定义标签的相关操作吧
目录
🥳🥳Welcome Huihui's Code World ! !🥳🥳
💡辉辉小贴士:学了这么多内容,那么我们到底在什么样的场景下会用到自定义标签呢?
导读:
在上篇我们已经说到了什么是标签,什么是jsp标签,以及为什么和字母使用自定义标签,有想了解详情的可以点此链接哦!
💡辉辉小贴士:学了这么多内容,那么我们到底在什么样的场景下会用到自定义标签呢?
自定义标签通常用于Web应用程序中,用于将业务逻辑从页面代码中抽象出来,从而简化页面代码并提高可重用性和可维护性。在使用自定义标签时,可以将页面代码与业务逻辑分离,使其更加松散耦合,使得应用程序更便于维护和扩展
具体来说,当您需要在多个页面中使用相同的HTML代码块或功能时,使用自定义标签可以将这些代码块封装到单个标签中,并在多个页面中重复使用。这也使得页面更具可读性和可维护性,因为标签更好地区分了页面上不同类型的代码块和功能
那么此篇就是让我们知道自定义标签的这个可以重复利用的特点!!!【多用实例演示哦~~】
一.自定义dept标签
- 用于遍历指定的数据(通常这个数据会在多个页面上被重复使用,例如我们所编写的这个标签是显示部门的信息的,然而部门信息通常在很多的页面上都需要显示与部门有关的信息,而我们也可以拘役反三,将其用于到其他的场景【会重复使用同一段数据信息】)
- 有一个变量来保存数据源
标签助手类
package com.wh.tag2; public class Dept { private int cid; private String cname; public Dept() { // TODO Auto-generated constructor stub } public Dept(int cid, String cname) { super(); this.cid = cid; this.cname = cname; } public int getCid() { return cid; } public void setCid(int cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } @Override public String toString() { return "MyClass [cid=" + cid + ", cname=" + cname + "]"; } }
tld文件【标签库描述文件】
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <!-- 标签库描述符 --> <taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor"> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>Simple Tags</short-name> <uri>wh</uri> <!--dept标签 --> <tag> <!-- 标签名字 --> <name>dept</name> <!-- 标签助手类的全路径名 --> <tag-class>com.wh.tag2.DeptTag</tag-class> <!-- 标签体内容==是否是空【不为空】 --> <body-content>jsp</body-content> <!-- 属性 --> <attribute> <!-- 属性名 --> <name>var</name> <!-- 属性是否必填 --> <required>true</required> <!-- 属性是否支持EL表达式 --> <rtexprvalue>false</rtexprvalue> <!-- 对dept标签属性作用的描述 --> <description>输出数据</description> </attribute> </tag> </taglib>
页面上引用
<%@page import="com.wh.tag2.Dept"%> <%@page import="java.util.ArrayList"%> <%@page import="java.util.List"%> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@taglib prefix="w" uri="wh" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>使用自定义标签</title> </head> <body> <% List<Object> list= new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); request.setAttribute("list", list); List<Dept> selectlist = new ArrayList<Dept>(); selectlist.add(new Dept(1, "摸鱼部🐟")); selectlist.add(new Dept(2, "撸猫部🐱")); selectlist.add(new Dept(3, "偷猪部🐖")); selectlist.add(new Dept(4, "遛狗部🐕")); request.setAttribute("selectlist", selectlist); %> <!-- out标签 --> <%-- <w:out val="123"/> --%> <!--if标签 --> <%-- <w:if test="${100 == 100}"> 结果为true,输出!! </w:if> <w:if test="${100 != 100}"> 结果为false,不输出!! </w:if> --%> <!-- foreach标签 --> <%-- <w:foreach items="${list }" var="l"> ${l } </w:foreach> --%> <!-- dept标签 --> <w:dept var="dept"></w:dept> ${dept } <w:select items="${selectlist }" optionVal="cid" optionText="cname" optionSelect="2"></w:select> </body> </html>
所用实体类
package com.wh.tag2; public class Dept { private int cid; private String cname; public Dept() { // TODO Auto-generated constructor stub } public Dept(int cid, String cname) { super(); this.cid = cid; this.cname = cname; } public int getCid() { return cid; } public void setCid(int cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } @Override public String toString() { return "MyClass [cid=" + cid + ", cname=" + cname + "]"; } }
结果
仔细看看自定义dept标签,是不是就很好的解决了重复同样代码的问题呢?那么下面的示例也是这样的
二.自定义ForEach标签
- 首先有一个变量保存数据源,也有你一个变量保存“指针”【就是遍历数据源时,这个变量会一个接着一个的指向数据源的数据】
- 如果数据源不为空的话,就遍历数据,如果为空的话,就跳过标签体
标签助手类
package com.wh.tag2; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; public class ForEachTag extends BodyTagSupport { private List<Object> items = new ArrayList<Object>(); private String var; public String getVar() { return var; } public void setVar(String var) { this.var = var; } public List<Object> getItems() { return items; } public void setItems(List<Object> items) { this.items = items; } @Override public int doStartTag() throws JspException { if(this.items==null||items.size()==0) { return SKIP_BODY; } Iterator<Object> it = items.iterator(); Object next = it.next(); this.pageContext.setAttribute(var, next); this.pageContext.setAttribute("it", it); return EVAL_BODY_INCLUDE; } @Override public int doAfterBody() throws JspException { Iterator<Object> it = (Iterator<Object>) this.pageContext.getAttribute("it"); if(it.hasNext()) { this.pageContext.setAttribute(var, it.next()); return EVAL_BODY_AGAIN; } return SKIP_BODY; } }
tld文件【标签库描述文件】
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <!-- 标签库描述符 --> <taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor"> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>Simple Tags</short-name> <uri>wh</uri> <!--foreach标签 --> <tag> <!-- 标签名字 --> <name>foreach</name> <!-- 标签助手类的全路径名 --> <tag-class>com.wh.tag2.ForEachTag</tag-class> <!-- 标签体内容==是否是空【不为空】 --> <body-content>jsp</body-content> <!-- 属性 --> <attribute> <!-- 属性名 --> <name>items</name> <!-- 属性是否必填 --> <required>true</required> <!-- 属性是否支持EL表达式 --> <rtexprvalue>true</rtexprvalue> <!-- 对if标签属性作用的描述 --> <description>遍历输出数据</description> </attribute> <attribute> <!-- 属性名 --> <name>var</name> <!-- 属性是否必填 --> <required>true</required> <!-- 属性是否支持EL表达式 --> <rtexprvalue>false</rtexprvalue> <!-- 对foreach标签属性作用的描述 --> <description>数据源的指针</description> </attribute> </tag> </taglib>
页面上引用
<%@page import="com.wh.tag2.Dept"%> <%@page import="java.util.ArrayList"%> <%@page import="java.util.List"%> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@taglib prefix="w" uri="wh" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>使用自定义标签</title> </head> <body> <% List<Object> list= new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); request.setAttribute("list", list); List<Dept> selectlist = new ArrayList<Dept>(); selectlist.add(new Dept(1, "摸鱼部🐟")); selectlist.add(new Dept(2, "撸猫部🐱")); selectlist.add(new Dept(3, "偷猪部🐖")); selectlist.add(new Dept(4, "遛狗部🐕")); request.setAttribute("selectlist", selectlist); %> <!-- out标签 --> <%-- <w:out val="123"/> --%> <!--if标签 --> <%-- <w:if test="${100 == 100}"> 结果为true,输出!! </w:if> <w:if test="${100 != 100}"> 结果为false,不输出!! </w:if> --%> <!-- foreach标签 --> <w:foreach items="${list }" var="l"> ${l } </w:foreach> <%-- <w:dept var="dept"></w:dept> ${dept } --%> <w:select items="${selectlist }" optionVal="cid" optionText="cname" optionSelect="2"></w:select> </body> </html>
结果
三.自定义select标签
标签助手类
package com.wh.tag2; import java.io.IOException; import java.lang.reflect.Field; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyTagSupport; public class SelectTag extends BodyTagSupport{ private List<Object> items; private String optionVal; private String optionText; private String optionSelect; public SelectTag() { // TODO Auto-generated constructor stub } public SelectTag(List<Object> items, String optionVal, String optionText, String optionSelect) { super(); this.items = items; this.optionVal = optionVal; this.optionText = optionText; this.optionSelect = optionSelect; } public List<Object> getItems() { return items; } public void setItems(List<Object> items) { this.items = items; } public String getOptionVal() { return optionVal; } public void setOptionVal(String optionVal) { this.optionVal = optionVal; } public String getOptionText() { return optionText; } public void setOptionText(String optionText) { this.optionText = optionText; } public String getOptionSelect() { return optionSelect; } public void setOptionSelect(String optionSelect) { this.optionSelect = optionSelect; } @Override public int doStartTag() throws JspException { //获取页面上下文对象 JspWriter out = this.pageContext.getOut(); try { out.print(PrintContent()); } catch (Exception e) { e.printStackTrace(); } return super.doStartTag(); } /** * 输出内容的方法 * @return * @throws Exception */ private String PrintContent() throws Exception { StringBuffer sb= new StringBuffer("<select>"); //往select标签中填充好内容【optionVal,optionText,optionSelect】 for (Object object : items) {//遍历数据源 String value=getObjectAttr(object,optionVal);//值 String text=getObjectAttr(object,optionText);//文本内容 sb.append("<option "+(value.equals(optionSelect) ?"selected" : " ")+" value ='"+value+"' >"+text+"</option>"); } sb.append("</select>"); return sb.toString(); } /** * 根据指定的对象那搭配指定的属性(名/值) * @return * @throws Exception * @throws NoSuchFieldException */ private String getObjectAttr(Object obj,String attr) throws Exception { Class class1 = obj.getClass();//类类 Field field = class1.getDeclaredField(attr);//拿到指定的属性 field.setAccessible(true);//允许拿到私有的属性 Object object = field.get(obj);//根据对象拿到里面的属性值 return object.toString();//返回拿到的属性值 } }
tld文件【标签库描述文件】
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <!-- 标签库描述符 --> <taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor"> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>Simple Tags</short-name> <uri>wh</uri> <!--select标签 --> <tag> <!-- 标签名字 --> <name>select</name> <!-- 标签助手类的全路径名 --> <tag-class>com.wh.tag2.SelectTag</tag-class> <!-- 标签体内容==是否是空【不为空】 --> <body-content>jsp</body-content> <!-- 属性 --> <attribute> <!-- 属性名 --> <name>items</name> <!-- 属性是否必填 --> <required>true</required> <!-- 属性是否支持EL表达式 --> <rtexprvalue>true</rtexprvalue> <!-- 对dept标签属性作用的描述 --> <description>数据源</description> </attribute> <attribute> <!-- 属性名 --> <name>optionVal</name> <!-- 属性是否必填 --> <required>true</required> <!-- 属性是否支持EL表达式 --> <rtexprvalue>true</rtexprvalue> <!-- 对dept标签属性作用的描述 --> <description>option的value值</description> </attribute> <attribute> <!-- 属性名 --> <name>optionText</name> <!-- 属性是否必填 --> <required>true</required> <!-- 属性是否支持EL表达式 --> <rtexprvalue>true</rtexprvalue> <!-- 对dept标签属性作用的描述 --> <description>option的文本值</description> </attribute> <attribute> <!-- 属性名 --> <name>optionSelect</name> <!-- 属性是否必填 --> <required>false</required> <!-- 属性是否支持EL表达式 --> <rtexprvalue>false</rtexprvalue> <!-- 对dept标签属性作用的描述 --> <description>option的选中状态</description> </attribute> </tag> </taglib>
页面上引用
<%@page import="com.wh.tag2.Dept"%> <%@page import="java.util.ArrayList"%> <%@page import="java.util.List"%> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@taglib prefix="w" uri="wh"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>使用自定义标签</title> </head> <body> <% List<Object> list= new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); request.setAttribute("list", list); List<Dept> selectlist = new ArrayList<Dept>(); selectlist.add(new Dept(1, "摸鱼部🐟")); selectlist.add(new Dept(2, "撸猫部🐱")); selectlist.add(new Dept(3, "偷猪部🐖")); selectlist.add(new Dept(4, "遛狗部🐕")); request.setAttribute("selectlist", selectlist); %> <!-- out标签 --> <%-- <w:out val="123"/> --%> <!--if标签 --> <%-- <w:if test="${100 == 100}"> 结果为true,输出!! </w:if> <w:if test="${100 != 100}"> 结果为false,不输出!! </w:if> --%> <!-- foreach标签 --> <%-- <w:foreach items="${list }" var="l"> ${l } </w:foreach> --%> <!-- dept标签 --> <%-- <w:dept var="dept"></w:dept> ${dept } --%> <w:select items="${selectlist }" optionVal="cid" optionText="cname" optionSelect="2"></w:select> </body> </html>
所用实体类
package com.wh.tag2; public class Dept { private int cid; private String cname; public Dept() { // TODO Auto-generated constructor stub } public Dept(int cid, String cname) { super(); this.cid = cid; this.cname = cname; } public int getCid() { return cid; } public void setCid(int cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } @Override public String toString() { return "MyClass [cid=" + cid + ", cname=" + cname + "]"; } }
结果
注意,这里选中了“偷猪部🐖”,是因为我在标签中设置了默认选中的就是它!!!
💡辉辉小贴士:那些我们常常烦的错,要注意啦!!!
- 在拼接的时候,常常会因为拼接的加号和引号之间没有空格,导致没有出现自己代码原本该出现的结果👇👇
- 我们在标签助手类中有时候会将属性的名字的首字母大写,因为我们内心是想遵循"驼峰命名法",但要是我们这样命名了,那么将会引发“找不到setters异常”👇👇
结果
那么为什么会出现这个错误呢?
在Java中,当我们在自定义标签时,如果属性名称在setters方法中大写,则会引发“找不到setters异常”(即找不到Java类中的相应属性的setter方法)。这是因为按照Java约定,属性名称的第一个字母应该是小写的,而setter方法名称应该以“set”开头,后面跟上首字母大写的属性名称。因此,如果我们的自定义标签属性名称中的第一个字母大写了,则在查找Java类的setter方法时,会寻找大写字母开头的方法,而不是与属性名完全相同的小写字母开头的方法
为了解决这个问题,我们应该在标签中使用与Java类属性名称完全相同的小写字母开头的属性名称这将确保可以正确绑定属性值到Java类对象,并正确地调用setter方法
好啦,今天的分享就到这了,希望能够帮到你呢!😊😊