JSP自定义标签(进阶)

简介: JSP自定义标签(进阶)

今天我们继续学习JSP自定义

 

一.面试题:String、StringBuffer和StringBuilder的异同?

相同点底层都是通过char数组实现的

不同点

1.String对象一旦创建,其值是不能修改的,如果要修改,会重新开辟内存空间来存储修改之后的对象;而StringBuffer和StringBuilder对象的值是可以被修改的;

2.StringBuffer几乎所有的方法都使用synchronized实现了同步,线程比较安全,在多线程系统中可以保证数据同步,但是效率比较低。

3.而StringBuilder 没有实现同步,线程不安全,在多线程系统中不能使用 StringBuilder,但是效率比较高

4.总结:如果我们在实际开发过程中需要对字符串进行频繁的修改。不要使用String,否则会造成内存空间的浪费;当需要考虑线程安全的场景下使用 StringBuffer,如果不需要考虑线程安全,追求效率的场景下可以使用 StringBuilder。

二.自定义foreach标签

我们在写jsp页面时会经常使用c标签的foreach标签。那么我们可不可以自己制定一个foreach标签提供自己使用呢?

下面我们来制定一个自定义foreach标签。

我们根据步骤来:

2.1 创建一个标签助手类(继承BodyTagSupport) 标签属性必须与助手类的属性对应、且要提供对应get/set方法

2.2 创建标签库描述文件(tld),添加自定义标签的配置 注:tld文件必须保存到WEB-INF目录或其子目录 jstl标签库

2.3 在JSP通过taglib指令导入标签库,并通过指定后缀访问自定义标签

运行效果:

 

2.1 创建一个标签助手类 ①(继承BodyTagSupport) ,且要②提供对应get/set方法,③重写doStartTag,doAfterBody,doEndTag方法

分析:定义两个私有的属性:  

    items;------ 用来遍历的

    var;--------用来保存添加的内容

代码如下:

package com.lya.tag;
import java.util.Iterator;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
/**
 * @author :JAVA-李永安
 * @date :2023年6月26日 下午6:44:00
 */
public class Foreachtag extends BodyTagSupport {
  private List items;// 用来遍历的
  private String var;// 用来保存添加的内容
  //提供对应get/set方法
  public List getItems() {
    return items;
  }
  public void setItems(List items) {
    this.items = items;
  }
  public String getVar() {
    return var;
  }
  public void setVar(String var) {
    this.var = var;
  }
  @Override
  public int doStartTag() throws JspException {
    if (items == null) {// 对集合判空
      return SKIP_BODY;// 为空就跳过
    } else {
      @SuppressWarnings("rawtypes")
      Iterator iterator = items.iterator();// 迭代遍历
      Object next = iterator.next();// 获取遍历内容
      pageContext.setAttribute(var, next);// 通过var保存遍历内容
      pageContext.setAttribute("iterator", iterator);// 保存未遍历的内容
      return EVAL_BODY_INCLUDE;
    }
  }
  @Override
  public int doAfterBody() throws JspException {
    // 将未遍历的内容继续遍历出来
    @SuppressWarnings("rawtypes")
    Iterator iterator = (Iterator) pageContext.getAttribute("iterator");// 获取未遍历的内容
    if (iterator.hasNext()) {// 对集合判空
      Object itp = iterator.next();// 获取遍历内容
      pageContext.setAttribute(var, itp);// 通过var保存遍历内容
      pageContext.setAttribute("iterator", iterator);// 保存未遍历的内容
      return EVAL_BODY_AGAIN;
    }
    return SKIP_BODY;
  }
  @Override
  public int doEndTag() throws JspException {
    // TODO Auto-generated method stub
    return SKIP_BODY;
  }
}

2.2 创建标签库描述文件(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的版本 -->
  <jsp-version>1.2</jsp-version>
  <!-- 你的标签库的简称 -->
  <short-name>test</short-name>
  <!-- 你标签库的引用uri -->
  <uri>/zking</uri><!-- 在jsp页面调用tld的路径 -->
  <tag>
    <!-- 标签名 -->
    <name>out</name>
    <!-- 标签工具类 -->
    <tag-class>com.lya.tag.outtag</tag-class>
    <!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
    <body-content>jsp</body-content>
    <!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
    <attribute>
      <!-- 自定义标签的属性名称 -->
      <name>aa</name>
      <!-- true表示必填 -->
      <required>true</required>
      <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
      <rtexprvalue>true</rtexprvalue>
      <description>out标签aa属性,输出aa</description>
    </attribute>
    <attribute>
      <!-- 自定义标签的属性名称 -->
      <name>bb</name>
      <!-- true表示必填 -->
      <required>false</required>
      <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
      <rtexprvalue>true</rtexprvalue>
      <description>默认输出</description>
    </attribute>
  </tag>
  <tag>
    <!-- 标签名 -->
    <name>if</name>
    <!-- 标签工具类 -->
    <tag-class>com.lya.tag.iftag</tag-class>
    <!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
    <body-content>jsp</body-content>
    <!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
    <attribute>
      <!-- 自定义标签的属性名称 -->
      <name>cc</name>
      <!-- true表示必填 -->
      <required>true</required>
      <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
      <rtexprvalue>true</rtexprvalue>
      <description>if标签cc属性,输出cc</description>
    </attribute>
  </tag>
  <tag>
    <!-- 标签名 -->
    <name>foreach</name>
    <!-- 标签工具类 -->
    <tag-class>com.lya.tag.Foreachtag</tag-class>
    <!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
    <body-content>jsp</body-content>
    <!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
    <attribute>
      <!-- 自定义标签的属性名称 -->
      <name>var</name>
      <!-- true表示必填 -->
      <required>true</required>
      <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
      <rtexprvalue>false</rtexprvalue><!-- var是string类型 -->
      <description>foreach标签cc属性,输出cc</description>
    </attribute>
    <attribute>
      <!-- 自定义标签的属性名称 -->
      <name>items</name>
      <!-- true表示必填 -->
      <required>true</required>
      <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
      <rtexprvalue>true</rtexprvalue>
      <description>foreach标签cc属性,输出cc</description>
    </attribute>
  </tag>
</taglib>

2.3 在JSP通过taglib指令导入标签库,使用自定义标签

<%@page import="java.util.Arrays"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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>Insert title here</title>
</head>
<body>
  <%
    request.setAttribute("name", "zs");
    List list = new ArrayList<>();
    list.add(0, "zs");
    list.add(1, "ls");
    list.add(2, "ww");
    List list2 = Arrays.asList(new String[] { "zs", "ls", "ww" });
    request.setAttribute("list", list);//通过request作用域保存list
  %>
  <pre>
  使用c标签的foreach标签遍历。
  </pre>
  <c:forEach items="${list }" var="a">
    ${a }<hr>
  </c:forEach>
  <pre>
  使用自定义foreach标签遍历。
  </pre>
  <z:foreach items="${list }" var="a">
    ${a }<hr>
  </z:foreach>
</body>
</html>

三.自定义select标签

3.1为啥我们需要自定义select标签?

 

1.以前我们使用jsp显示内容是使用servlet传递参数(步骤比较繁琐),只要写两行代码。

以前写的:

使用自定义select标签后写的:

显示的效果:

 

2.那么我们用一种简洁的代码来完成。

3.提升我们代码的可维护能力。

3.2创建自定义select标签步骤:

3.2.1 创建一个标签助手类 ①(继承BodyTagSupport) ,且要②提供对应get/set方法,③重写doStartTag,doAfterBody,doEndTag方法

分析:1.定义两个私有的属性:  

   items;---- 用来遍历的

   

   textval;----用来显示下拉的内容

   textvalue;----- 传递下拉对应的value

   seleteval;------- 传递值,使页面显示对应的内容

        2.提供无参构造(因为这个select标签要被作为公共的标签,可是对应的对象我们又不知道,这时候我们得用到反射来实现)

        3.重写doStartTag方法

        4.使用stringbuffer拼接

代码如下:

package com.lya.tag;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import com.lya.entity.Dpat;
/**
 * 下拉框的标签助手类
 * 
 * @author :JAVA-李永安
 * @date :2023年6月26日 下午7:52:46
 */
public class SeleteTag extends BodyTagSupport{
  private List items;// 用来遍历的
  private String textval;// 用来显示下拉的内容
  private String textvalue;// 传递下拉对应的value
  private String seleteval;// 传递值,使页面显示对应的内容
  //提供无参构造(因为这个select标签要被作为公共的标签,可是对应的对象我们又不知道,这时候我们得用到反射来实现)
  //提供对应get/set方法
  public List getItems() {
    return items;
  }
  public void setItems(List items) {
    this.items = items;
  }
  public String getTextval() {
    return textval;
  }
  public void setTextval(String textval) {
    this.textval = textval;
  }
  public String getTextvalue() {
    return textvalue;
  }
  public void setTextvalue(String textvalue) {
    this.textvalue = textvalue;
  }
  public String getSeleteval() {
    return seleteval;
  }
  public void setSeleteval(String seleteval) {
    this.seleteval = seleteval;
  }
  @Override
  public int doStartTag() throws JspException {
    //1.使用页面输出流
    JspWriter out = pageContext.getOut();
    //2.定义一个空变量,通过字符串的方式保存向页面显示的内容
    try {
      out.print(html());
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
      return EVAL_BODY_INCLUDE;
    }
  private String html() throws Exception {
    //1.实例stringbuffer,用于去拼接字符串。
    StringBuffer sb = new StringBuffer();
    sb.append("<select>");
    //2.使用反射 (输出的内容取决于items集合的内容)
    for (Object object : items) {
      //3.取出对象的属性值
      String var = getobjvalue(object,textval);//显示内容
      String value = getobjvalue(object,textvalue);//value
      sb.append("<option "+(value.equals(seleteval) ? "selected" : "")+" value='"+value+"'>"+var+"</option>");
    }
    sb.append("</select>");
    return sb.toString();//转成string输出
  }
  /**
   * 取出对象的属性值
   * @param object
   * @param value
   * @return
   * @throws SecurityException 
   * @throws NoSuchFieldException 
   */
  private String getobjvalue(Object object, String value) throws Exception {
    //实例类类
    Class class1 = object.getClass();
    //取得的对应的属性
    Field declaredField = class1.getDeclaredField(value);
    //获取权限
    declaredField.setAccessible(true);
    return declaredField.get(object).toString();
  }
  @Override
  public int doEndTag() throws JspException {
    // TODO Auto-generated method stub
    return SKIP_BODY;
  }
}

         

3.2.2 创建标签库描述文件(tld)

将助手类对应的属性进行描述:注意不要copy错误了!!!

代码如下:

<!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的版本 -->
  <jsp-version>1.2</jsp-version>
  <!-- 你的标签库的简称 -->
  <short-name>test</short-name>
  <!-- 你标签库的引用uri -->
  <uri>/zking</uri><!-- 在jsp页面调用tld的路径 -->
  <tag>
    <!-- 标签名 -->
    <name>select</name>
    <!-- 标签工具类 -->
    <tag-class>com.lya.tag.SeleteTag</tag-class>
    <!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
    <body-content>jsp</body-content>
    <!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
    <attribute>
      <!-- 自定义标签的属性名称 -->
      <name>items</name>
      <!-- true表示必填 -->
      <required>true</required>
      <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
      <rtexprvalue>true</rtexprvalue>
      <description>select标签保存的集合</description>
    </attribute>
    <attribute>
      <!-- 自定义标签的属性名称 -->
      <name>textval</name>
      <!-- true表示必填 -->
      <required>true</required>
      <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
      <rtexprvalue>false</rtexprvalue><!-- var是string类型 -->
      <description>select标签输出的内容</description>
    </attribute>
    <attribute>
      <!-- 自定义标签的属性名称 -->
      <name>textvalue</name>
      <!-- true表示必填 -->
      <required>true</required>
      <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
      <rtexprvalue>false</rtexprvalue><!-- var是string类型 -->
      <description>select标签输出的value值</description>
    </attribute>
    <attribute>
      <!-- 自定义标签的属性名称 -->
      <name>seleteval</name>
      <!-- true表示必填 -->
      <required>false</required>
      <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
      <rtexprvalue>false</rtexprvalue><!-- var是string类型 -->
      <description>select传递值,使页面显示对应的内容</description>
    </attribute>
  </tag>
</taglib>

3.2.3 在JSP通过taglib指令导入标签库,使用自定义标签

注意不要写标签时不要写错误了,最好通过快捷方式!!!

代码如下:

<%@page import="com.lya.entity.Dpat"%>
<%@page import="java.util.Arrays"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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>Insert title here</title>
</head>
<body>
  <%
    request.setAttribute("name", "zs");
    List list = new ArrayList<>();
    list.add(0, "zs");
    list.add(1, "ls");
    list.add(2, "ww");
    List<Dpat> list2 = new ArrayList<Dpat>();
    list2.add(new Dpat("0", "学历部"));
    list2.add(new Dpat("1", "产品部"));
    list2.add(new Dpat("2", "电竞部"));
    list2.add(new Dpat("3", "..."));
    request.setAttribute("list", list);//通过request作用域保存list
    request.setAttribute("list2", list2);//通过request作用域保存list
  %>
  <pre>
  使用自定义select标签。
  </pre>
  <select>
    <z:foreach items="${list }" var="a">
      <option>${a }</option>
    </z:foreach>
  </select>
  <hr>
<z:select items="${list2 }" textvalue="did" textval="dname"></z:select>
<z:select items="${list2 }" textvalue="did" textval="dname" seleteval="1"></z:select>
<z:select items="${list2 }" textvalue="did" textval="dname" seleteval="2"></z:select>
<z:select items="${list2 }" textvalue="did" textval="dname" seleteval="3"></z:select>
</body>
</html>

四.总结

我们在写助手类时,1.要牢记自己定义的属性名称,

                                2.使用StringBuffer进行拼接要小心,注意单引号双引号的转换      

                                3.编写描述类时不要将助手类的名称写错!!!

                                 最后注意逻辑的梳理!!!

                               希望本篇讲解能帮助到你!!!😀

目录
相关文章
|
5月前
|
Java
JSP自定义标签【下】
JSP自定义标签【下】
50 0
|
6月前
|
Java
jsp自定义标签
jsp自定义标签
43 1
|
23天前
|
Java 数据安全/隐私保护
Jsp自定义标签(foreach,dept,select)
Jsp自定义标签(foreach,dept,select)
28 0
|
4月前
|
XML Java 数据格式
JSP自定义标签
JSP自定义标签
53 0
|
5月前
|
存储 Java 开发者
JSP自定义标签(下)
JSP自定义标签(下)
39 0
|
5月前
|
XML Java 数据格式
JSP自定义标签
JSP自定义标签
33 0
|
5月前
|
XML Java 数据格式
JSP自定义标签
JSP自定义标签
42 0
|
5月前
|
Java API
JSP自定义标签【上】
JSP自定义标签【上】
36 0
|
6月前
|
XML Java 数据格式
JSP自定义标签(基础)
JSP自定义标签(基础)
22 0
|
6月前
|
Java 开发者
JSP自定义标签
JSP自定义标签
31 0