一、自定义数据标签
第一步:定义对象
以学生实体为例
package com.ctb.tag; /** * 学生实体 * @author biao * */ public class Student { private String sid; private String sname; public Integer age; public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Student() { super(); } public Student(String sid) { super(); this.sid = sid; } public Student(String sid, String sname) { super(); this.sid = sid; this.sname = sname; } @SuppressWarnings("unused") private Student(Integer age) { this.age = age; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Student(String sid, String sname, Integer age) { super(); this.sid = sid; this.sname = sname; this.age = age; } @Override public String toString() { return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]"; } }
第二步:定义助手类
package com.ctb.tagg; import java.util.ArrayList; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.TagSupport; import com.ctb.tag.Student; /** * 数据标签助手类 * @author biao * */ public class StudentTag extends TagSupport{ private String var; public String getVar() { return var; } public void setVar(String var) { this.var = var; } @Override public int doStartTag() throws JspException { //模拟数据 List<Student> list=new ArrayList<Student>(); list.add(new Student("c001", "小问", 18)); list.add(new Student("c002", "卡卡", 13)); list.add(new Student("c003", "溜你", 42)); list.add(new Student("c004", "苦行僧",23)); //将数据放入var中 pageContext.setAttribute(var, list); return SKIP_BODY; } }
第三步:定义tld文件
<tag> <name>student</name> <tag-class>com.ctb.tagg.StudentTag</tag-class> <body-content>jsp</body-content> <attribute> <name>var</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> </tag>
第四步:jsp页面
<p>Student标签</p> <c:student var="s" /> ${s }<hr>
第五步:输出结果
1.select标签
使用select标签无疑就是要用到下拉按钮,在下来按钮中我们可以设置样式,可以设置id,可以设置name属性,还可以设置默认选中的值。所以这些都是我们在定义select标签中需要考虑的。那接下来就可以开始我们的助手类了
2.定义助手类
package com.ctb.tagg; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; /** * 自定义select标签 * @author biao * */ public class SelectTag extends TagSupport{ private List<Object> items=new ArrayList<Object>();//数据源 private String optionVal;//id private String optionText;//name private String selectedVal;//选中的id 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 getSelectedVal() { return selectedVal; } public void setSelectedVal(String selectedVal) { this.selectedVal = selectedVal; } //反射--提供无参构造器 public SelectTag() { // TODO Auto-generated constructor stub } public SelectTag(List<Object> items, String optionVal, String optionText, String selectedVal) { super(); this.items = items; this.optionVal = optionVal; this.optionText = optionText; this.selectedVal = selectedVal; } @Override public int doStartTag() throws JspException { //获取输出对象 JspWriter out = pageContext.getOut(); try { //输出select标签拼接内容 out.print(toHTML()); } catch (Exception e) { e.printStackTrace(); } return SKIP_BODY; } /** * 拼接select标签内容 * @return * @throws Exception */ private String toHTML() throws Exception { //StringBuffed拼接效率高,消耗内存少 StringBuffer sb=new StringBuffer("<select>"); //遍历 for (Object object : items) { //获取实体id与下拉列表名称 String val=getObjAttrValue(object,optionVal); String text=getObjAttrValue(object,optionText); //拼接 sb.append("<option "+(val.equals(selectedVal) ? "selected" : "")+" value='"+val+"'>"+text+"</option>"); } sb.append("</select>"); //返回结果 return sb.toString(); } /** * 获取某个对象的某个属性值 * @param object 实体 * @param attr 属性 * @return * @throws Exception * */ private String getObjAttrValue(Object object, String attr) throws Exception { //获取类类 Class class1 = object.getClass(); //读取属性 Field f = class1.getDeclaredField(attr); //打开权限 f.setAccessible(true); return f.get(object).toString(); } }
<tag> <name>select</name> <tag-class>com.ctb.tagg.SelectTag</tag-class> <body-content>jsp</body-content> <attribute> <!-- 属性名 --> <name>items</name> <!-- 是否为必须的 --> <required>true</required> <!-- 是否支持EL表达式 --> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>optionVal</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>optionText</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>selectedVal</name> <required>false</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag>
4.jsp页面
<% //首先是先定义一个实体对象 //插入数据 List<Hobby> list=new ArrayList<Hobby>(); list.add(new Hobby(1,"大卫")); list.add(new Hobby(2,"调试")); list.add(new Hobby(3,"毒跑")); list.add(new Hobby(4,"莎妮")); list.add(new Hobby(5,"得得")); request.setAttribute("list", list); %> <p>select标签</p> <c:select items="${list }" optionVal="hid" optionText="hname" ></c:select> <c:select items="${list }" optionVal="hid" optionText="hname" selectedVal="2"></c:select> <c:select items="${list }" optionVal="hid" optionText="hname" selectedVal="4"></c:select>
5.输出结果
三、注意事项
在JSP中自定义标签时,需要遵循以下注意事项:
- 确认需求:在开始编写自定义标签前,需要仔细了解需求并确认标签的具体功能和作用。
- 设计标签:设计标签时需要考虑到标签的语法格式、标签行为、标签属性以及标签体等元素。
- 编写标签处理器:为了处理自定义标签的行为和属性,需要编写Java类表示处理器来执行标签的逻辑操作。
- 标签库描述文件:需要编写标签库描述文件(TLD)来指定标签的名称、语法格式、属性以及它们的数据类型和描述信息。
- 标签库的创建和组织:为了使用自定义标签,需要将标签库文件和标签处理器类放在正确的位置,JSP引擎在解析时才能识别标签库。
- 命名空间和前缀:在使用自定义标签时,需要使用命名空间和前缀来引用标签库文件,以防止多个标签库之间的命名冲突。
- 遵循规范:在编写自定义标签时,需要遵循Java EE平台的规范,特别是JSP 2.0规范,以保证标签的兼容性和可移植性。
- 测试和调试:在完成标签的编写后,需要进行测试和调试,确保标签能够正常工作。
四、面试题 String,StringBuilder,StringBuffer这三个有什么区别呢?
1.String类
String类是Java中最基本的字符串类,并且它是不可变的。一旦String对象被创建,它的值就不可以被改变。如果想修改String对象中的字符内容,就必须创建一个新的String对象。这也是String类的局限所在,它限制了字符串的可变性,导致在频繁拼接字符串的操作中,性能明显下降。
2.StringBuilder类
StringBuilder是一个可变的字符串容器,它可以进行频繁的字符串操作,并且不用每次都创建新的StringBuilder对象。StringBuilder的实现方式是通过一个可变的char数组来存储字符串内容,每当append字符时,就往数组中添加字符。StringBuilder的对象在内存空间中是可以修改的,因此可以有效地减少频繁进行对象创建和销毁的开销,提升字符串操作的效率。但是,StringBuilder不是线程安全的。
3.StringBuffer类
和StringBuilder类似,StringBuffer也是一个可变的字符串容器。它的实现原理与StringBuilder类似,都是采用可变的char数组来存储字符串。不同的是,StringBuffer是线程安全的,它的操作方法都被封装成了同步方法,保证了在多线程并发操作中的线程安全性。但是,由于线程同步是需要消耗额外的系统资源的,所以StringBuffer的执行效率略低于StringBuilder。
欢迎大家评论区留言😊😊😊