自定义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 + "]";
  }
}
相关文章
|
7月前
|
SQL XML Java
JSP 教程 之 JSP 标准标签库(JSTL) 4
**JSP的JSTL是用于简化Web开发的标签库,包括核心、格式化、SQL、XML和函数5个部分。SQL标签库允许与数据库交互,如设定数据源、执行查询和更新,以及处理参数。例如, `&lt;sql:setDataSource&gt;` 定义数据源, `&lt;sql:query&gt;` 执行查询。通过使用JSTL,开发者能更整洁地处理JSP页面。**
58 8
|
7月前
|
XML SQL Java
JSP 教程 之 JSP 标准标签库(JSTL) 1
JSP的JSTL是用于简化页面逻辑的标签库,涵盖核心、格式化、SQL、XML和函数五大类标签。要安装,下载Apache的JSTL包,将jar文件放入WEB-INF/lib,tld文件复制到WEB-INF,并在web.xml中配置相应的taglib信息。JSTL促进了JSP页面的清洁和结构化。
53 5
|
7月前
|
XML SQL Java
JSP 教程 之 JSP 标准标签库(JSTL) 6
**JSP JSTL 摘要:** JSTL是JSP的标签库,包含核心、格式化、SQL、XML和函数5类标签。它用于执行常见任务,如迭代、条件判断和XML操作。JSTL函数库提供字符串处理函数,如`contains()`, `endsWith()`, `escapeXml()`等,方便XML和HTML处理。通过`&lt;%@ taglib %&gt;`导入,如`fn:trim()`用于去除字符串两端空白。
49 5
|
7月前
|
Java 应用服务中间件 Android开发
完成你的自定义JSP Tag标签-Basic Coustom Tag
完成你的自定义JSP Tag标签-Basic Coustom Tag
36 0
|
8月前
|
Java
jsp页面中使用jstl标签报错:javax.servlet.jsp.JspTagException
jsp页面中使用jstl标签报错:javax.servlet.jsp.JspTagException
119 0
|
3月前
|
Java 容器
【学习笔记】Jsp与Servlet技术
【学习笔记】Jsp与Servlet技术
93 0
|
5月前
|
SQL Java 数据库
jsp中使用Servlet查询SQLSERVER数据库中的表的信息,并且打印在屏幕上
该博客文章介绍了在JSP应用中使用Servlet查询SQL Server数据库的表信息,并通过JavaBean封装图书信息,将查询结果展示在Web页面上的方法。
jsp中使用Servlet查询SQLSERVER数据库中的表的信息,并且打印在屏幕上
|
5月前
|
供应链 前端开发 Java
JSP+servlet+mybatis+layui服装库存管理系统(大三上学期课程设计)
这篇文章通过一个服装库存管理系统的实例,展示了在Spring Boot项目中使用Ajax、JSON、layui、MVC架构和iframe等技术,涵盖了注册登录、权限管理、用户管理、库存管理等功能,并提供了系统运行环境和技术要求的详细说明。
JSP+servlet+mybatis+layui服装库存管理系统(大三上学期课程设计)
|
5月前
|
前端开发 安全 Java
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
35 0
|
7月前
|
自然语言处理 前端开发 Java
Servlet与JSP:Java Web开发的基石技术详解
【6月更文挑战第23天】Java Web的Servlet与JSP是动态网页的核心。Servlet是服务器端的Java应用,处理HTTP请求并响应;JSP则是结合HTML与Java代码的页面,用于动态内容生成。Servlet通过生命周期方法如`init()`、`service()`和`destroy()`工作,而JSP在执行时编译成Servlet。两者在MVC架构中分工,Servlet处理逻辑,JSP展示数据。尽管有Spring MVC等框架,Servlet和JSP仍是理解Web开发基础的关键。
130 12