自定义JSP[if,foreach,数据,select]标签

简介: 自定义JSP[if,foreach,数据,select]标签

自定义if标签(后续三个标签都是这个步骤)


第一步:写业务


第二步:定义助手类


第三步:定义tld文件


第四步:使用自定义jsp标签(在同一个页面,放在文章的最后,名字叫index.jsp)



第一步:写业务:if标签的test属性必须是一个boolean类型的值,如果test的值为true,那么执行if标签的内容,否则不执行。

第二步:定义助手类

package com.zking.jsptag.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
//助手类
public class IfTag extends BodyTagSupport{
  private boolean test;
  @Override
  public int doStartTag() throws JspException {
  if(test)
    return EVAL_BODY_INCLUDE;
  else
    return SKIP_BODY;
  }
  @Override
  public int doEndTag() throws JspException {
  // TODO Auto-generated method stub
  return EVAL_PAGE;
  }
  public boolean isTest() {
  return test;
  }
  public void setTest(boolean test) {
  this.test = test;
  }
}

第三步:定义tld文件:tld文件的属性名是什么意思我就不在赘述了,这个也在我前面一篇文章里面讲解了。当我们tld文件定义好后就可以开始在页面上使用自定义jsp标签了

<!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>z</short-name>
  <!-- 你标签库的引用uri -->
  <uri>/zking</uri>
<tag>
  <!-- 标签名 -->
  <name>if</name>
  <!-- 标签工具类 -->
  <!-- Class.forName("com.zking.jsptag.tag.TestTag") -->
  <tag-class>com.zking.jsptag.tag.IfTag</tag-class>
  <!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
  <body-content>jsp</body-content>
  <!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
  <attribute>
    <!-- 自定义标签的属性名称 -->
    <name>test</name>
    <!-- true表示必填 -->
    <required>true</required>
    <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
    <rtexprvalue>true</rtexprvalue>
  </attribute>
  </tag>


自定义foreach标签


第一步:写业务:

在定义foreach标签时我们需要了解它的业务是什么:很显然foreach标签需要得到一个集合,然后再这个集合的基础上遍历这个集合。当我们清楚业务逻辑后就可以开始定义foreach标签了。既然是需要得到一个集合,然后再遍历这个集合。那我们就知道了需要两个属性,一个是得到一个集合属性,另一个是遍历这个集合的值。

第二步:定义助手类

package com.zking.jsptag.tag;
import java.util.Collection;
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 Object items;
  private List items;
  //每次遍历所定义的变量名,实际上在这里是将每次循环遍历的结果保存到指定作用域,并以var属性命名
  //  for(String obj : items) {
  //  pageContext.setAttribute("n", obj);
  //  }
  //var=n -> ${n}
  private String var;
  @Override
  public int doStartTag() throws JspException {
  // TODO Auto-generated method stub
  //if(items instanceof Collection)
  //else if(items instanceof Object[])
  //判断items是否为空
  if(null==items) {
    return SKIP_BODY;
  }else {
    //获取items的迭代器
    Iterator it = items.iterator();
    //获取迭代器中的下一个元素(移动下标)
    Object value = it.next();
    //将获取的值保存到page作用域中,并以var来命名
    //pageContext.setAttribute("n", "zs"); -> ${n}
    pageContext.setAttribute(var, value);
    //将剩余未遍历完成的迭代器对象保存到page作用域,留到doAfterBody中再次进行遍历
    pageContext.setAttribute("it", it);
    return EVAL_BODY_INCLUDE;
  }
  }
  @Override
  public int doAfterBody() throws JspException {
  //将剩余未遍历完的迭代器取出来
  Iterator it = (Iterator) pageContext.getAttribute("it");
  //使用if判断,判断迭代器中的下一个元素是否存在
  if(it.hasNext()) {
    //获取迭代器中的下一个元素(移动下标)
    Object value = it.next();
    //将获取的值保存到page作用域中,并以var来命名
    //pageContext.setAttribute("n", "zs"); -> ${n}
    pageContext.setAttribute(var, value);
    //将剩余未遍历完成的迭代器对象保存到page作用域,留到doAfterBody中再次进行遍历
    pageContext.setAttribute("it", it);
    return EVAL_BODY_AGAIN;
  }else {
    return SKIP_BODY;
  }
  }
  @Override
  public int doEndTag() throws JspException {
  // TODO Auto-generated method stub
  return EVAL_PAGE;
  }
  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;
  }
}

第三步:定义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>z</short-name>
  <!-- 你标签库的引用uri -->
  <uri>/zking</uri>
<tag>
  <!-- 标签名 -->
  <name>forEach</name>
  <!-- 标签工具类 -->
  <!-- Class.forName("com.zking.jsptag.tag.TestTag") -->
  <tag-class>com.zking.jsptag.tag.ForeachTag</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>
  </attribute>
  <attribute>
    <!-- 自定义标签的属性名称 -->
    <name>var</name>
    <!-- true表示必填 -->
    <required>true</required>
    <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
    <rtexprvalue>false</rtexprvalue>
  </attribute>
  </tag>


自定义数据(data)标签


第一步:写业务

第二步:定义助手类

package com.zking.jsptag.tag;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import com.zking.jsptag.entity.Dept;
import com.zking.jsptag.entity.RoleType;
/**
 * 助手类
 * 自定义的数据标签,大家可以参考从数据库中获取数据,此案例用的是静态数据
 * @author Administrator
 *
 */
public class DeptTag extends BodyTagSupport {
  //将查询出来的数据保存到指定的作用域,并以var属性命名
  private String var;
  //可以通过该参数指明你所需要存储的作用域(page/request/session/application)默认page
  private String scope;
  @Override
  public int doStartTag() throws JspException {
  //1)从数据库中查询数据(大家自行考虑)
  //2)本案例的静态数据填充
  /*List<Dept> lst = new ArrayList<>();
  lst.add(new Dept(1,"研发部"));
  lst.add(new Dept(2,"人事部"));
  lst.add(new Dept(3,"市场部"));*/
  List<RoleType> lst = new ArrayList<>();
  lst.add(new RoleType(1,"管理员"));
  lst.add(new RoleType(2,"高级用户"));
  lst.add(new RoleType(3,"普通用户"));
  //获取Request对象
  HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
  //获取Session对象
  HttpSession session = request.getSession();
  //获取Application
  ServletContext application = pageContext.getServletContext();
  //判断scope
  if(null==scope) {
    pageContext.setAttribute(var, lst);
  }else if(scope.equals("request")) {
    request.setAttribute(var, lst);
  }else if(scope.equals("session")) {
    request.setAttribute(var, lst);
  }else if(scope.equals("application")) {
    request.setAttribute(var, lst);
  }else {
    pageContext.setAttribute(var, lst);
  }
  return SKIP_BODY;
  }
  @Override
  public int doEndTag() throws JspException {
  // TODO Auto-generated method stub
  return EVAL_PAGE;
  }
  public String getVar() {
  return var;
  }
  public void setVar(String var) {
  this.var = var;
  }
  public String getScope() {
  return scope;
  }
  public void setScope(String scope) {
  this.scope = scope;
  }
}

第三步:定义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>z</short-name>
  <!-- 你标签库的引用uri -->
  <uri>/zking</uri>
<tag>
  <!-- 标签名 -->
  <name>dept</name>
  <!-- 标签工具类 -->
  <!-- Class.forName("com.zking.jsptag.tag.TestTag") -->
  <tag-class>com.zking.jsptag.tag.DeptTag</tag-class>
  <!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
  <body-content>empty</body-content>
  <!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
  <attribute>
    <!-- 自定义标签的属性名称 -->
    <name>var</name>
    <!-- true表示必填 -->
    <required>true</required>
    <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
    <rtexprvalue>false</rtexprvalue>
  </attribute>
  <attribute>
    <!-- 自定义标签的属性名称 -->
    <name>scope</name>
    <!-- true表示必填 -->
    <required>false</required>
    <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
    <rtexprvalue>false</rtexprvalue>
  </attribute>
  </tag>


自定义select标签


第一步:写业务:使用select标签无疑就是要用到下拉按钮,在下来按钮中我们可以设置样式,可以设置id,可以设置name属性,还可以设置默认选中的值。所以这些都是我们在定义select标签中需要考虑的。那接下来就可以开始我们的助手类了

第二步:定义助手类

package com.zking.jsptag.tag;
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 {
  //被遍历的集合或数组List<Dept> -> Dept [deptId,deptName]
  private List items;
  //用于指定绑定到option标签中的value属性的值,值可以被理解为循环遍历对象中的属性名
  //例如:optionValue="deptId"
  private String optionValue;
  //用于指定绑定到option标签中的标签体的值,值可以被理解为循环遍历对象中的属性名
  //例如:optionText="deptName"
  private String optionText;
  @Override
  public int doStartTag() throws JspException {
  try {
    JspWriter out = pageContext.getOut();
    //编写逻辑
    out.write(toSelect());
  } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
  }
  return SKIP_BODY;
  }
  private String toSelect() {
  //面试题:String/StringBuffer/StringBuilder的区别
  StringBuffer sb = new StringBuffer();
  //拼接<select>
  sb.append("<select>");
  //拼接请选择
  sb.append("<option value=''>----请选择----</option>");
  //循环遍历items,用于循环生成option标签
  //此处的obj就是Dept,obj可以是任意对象
  for(Object obj : items) {
    //问题:如何从obj中取出对应的属性的值,由optionValue和optionText来决定
    String value = this.getObjValue(obj, this.optionValue);
    String text = this.getObjValue(obj, this.optionText);
    //拼接option标签
    sb.append("<option value='"+value+"'>"+text+"</option>");
  }
  //拼接</select>
  return sb.toString();
  }
  private String getObjValue(Object obj,String fieldName) {
  String value = null;
  try {
    //一切和反射相关的代码都是从获取类对象开始
    Class cls = obj.getClass();
    //获取对象的属性数组
    Field[] fields = cls.getDeclaredFields();
    //循环遍历属性
    for (Field field : fields) {
    //将对象中的属性名与传入的fieldName进行比较,如果相同,则获取数据,不相同,则不获取数据
    if(field.getName().toUpperCase().equals(fieldName.toUpperCase())) {
      //设置访问权限
      field.setAccessible(true);
      //获取数据
      value = field.get(obj).toString();
    }
    }
  } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
  }
  return value;
  }
  @Override
  public int doEndTag() throws JspException {
  // TODO Auto-generated method stub
  return EVAL_PAGE;
  }
  public List getItems() {
  return items;
  }
  public void setItems(List items) {
  this.items = items;
  }
  public String getOptionValue() {
  return optionValue;
  }
  public void setOptionValue(String optionValue) {
  this.optionValue = optionValue;
  }
  public String getOptionText() {
  return optionText;
  }
  public void setOptionText(String optionText) {
  this.optionText = optionText;
  }
}


第三步:定义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>z</short-name>
  <!-- 你标签库的引用uri -->
  <uri>/zking</uri>
<tag>
  <!-- 标签名 -->
  <name>select</name>
  <!-- 标签工具类 -->
  <!-- Class.forName("com.zking.jsptag.tag.TestTag") -->
  <tag-class>com.zking.jsptag.tag.SelectTag</tag-class>
  <!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
  <body-content>empty</body-content>
  <!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
  <attribute>
    <!-- 自定义标签的属性名称 -->
    <name>items</name>
    <!-- true表示必填 -->
    <required>true</required>
    <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
    <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
    <!-- 自定义标签的属性名称 -->
    <name>optionValue</name>
    <!-- true表示必填 -->
    <required>true</required>
    <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
    <rtexprvalue>false</rtexprvalue>
  </attribute>
  <attribute>
    <!-- 自定义标签的属性名称 -->
    <name>optionText</name>
    <!-- true表示必填 -->
    <required>true</required>
    <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
    <rtexprvalue>false</rtexprvalue>
  </attribute>
  </tag>
</taglib>

private String html()方法

在这个方法中我们需要显示下拉款功能。因为我们是需要使用在jsp页面中的,所以我们需要在这个方法中写入HTML代码。在java代码中要写入HTML代码的话就需要使用拼接的方式来完成。这里有三种方法,第一个StringBuilder,第二个String,第三个StringBuffer。这三个有什么区别呢?(面试题)

StringBuilder

线程不安全,但是在使用拼接的时候速度会很快

String

在每次new的时候会产生新的节点,但是在jdk8之后使用拼接是跟StringBuilder一样的效果

StringBuffer

线程安全,但是速度慢


对应上面的这些,我有两个实体类,下面给你们把代码放出来,第一个是Dept.java,第二个是RoleType.java

package com.zking.jsptag.entity;
import java.io.Serializable;
public class Dept implements Serializable {
  private Integer deptId;
  private String deptName;
  public Integer getDeptId() {
  return deptId;
  }
  public void setDeptId(Integer deptId) {
  this.deptId = deptId;
  }
  public String getDeptName() {
  return deptName;
  }
  public void setDeptName(String deptName) {
  this.deptName = deptName;
  }
  public Dept() {
  super();
  }
  public Dept(Integer deptId, String deptName) {
  super();
  this.deptId = deptId;
  this.deptName = deptName;
  }
  @Override
  public String toString() {
  return "Dept [deptId=" + deptId + ", deptName=" + deptName + "]";
  }
}
package com.zking.jsptag.entity;
import java.io.Serializable;
public class RoleType implements Serializable{
  private Integer roleId;
  private String roleName;
  public Integer getRoleId() {
  return roleId;
  }
  public void setRoleId(Integer roleId) {
  this.roleId = roleId;
  }
  public String getRoleName() {
  return roleName;
  }
  public void setRoleName(String roleName) {
  this.roleName = roleName;
  }
  public RoleType() {
  super();
  }
  public RoleType(Integer roleId, String roleName) {
  super();
  this.roleId = roleId;
  this.roleName = roleName;
  }
  @Override
  public String toString() {
  return "RoleType [roleId=" + roleId + ", roleName=" + roleName + "]";
  }
}
相关文章
|
29天前
|
Java 应用服务中间件
jsp数据交互(一)
jsp数据交互(一)
10 0
|
2月前
|
Java
jsp页面中使用jstl标签报错:javax.servlet.jsp.JspTagException
jsp页面中使用jstl标签报错:javax.servlet.jsp.JspTagException
13 0
|
12天前
|
Java 数据安全/隐私保护
Jsp自定义标签(foreach,dept,select)
Jsp自定义标签(foreach,dept,select)
28 0
|
4月前
|
Java
jsp标签下
jsp标签下
26 0
|
4月前
|
XML Java 数据格式
jsp标签上
jsp标签上
25 0
|
4月前
|
Java
JSP标签(2) -----自定义foreach ,select标签,全网最详细,最完整易懂
JSP标签(2) -----自定义foreach ,select标签,全网最详细,最完整易懂
|
18天前
|
Java
学校教师管理系统【JSP+Servlet+JavaBean】(Java课设)
学校教师管理系统【JSP+Servlet+JavaBean】(Java课设)
19 1
|
18天前
|
Java
人事管理系统【JSP+Servlet+JavaBean】(Java课设)
人事管理系统【JSP+Servlet+JavaBean】(Java课设)
16 0
|
18天前
|
Java
排课系统【JSP+Servlet+JavaBean】(Java课设)
排课系统【JSP+Servlet+JavaBean】(Java课设)
7 0
|
18天前
|
Java
仓库管理系统【JSP+Servlet+JavaBean】(Java课设)
仓库管理系统【JSP+Servlet+JavaBean】(Java课设)
12 0