自定义JSP标签

本文介绍了JSP自定义标签的概念,包括标签库的含义和自定义标签的生命周期。详细讲解了如何创建自定义标签,涉及编写助手类、定义tld文件以及在JSP页面中的使用。同时,列举了UI标签、控制标签、数据标签和空标签的示例,帮助读者掌握自定义标签的开发过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、什么是标签

标记语言,是一种注释文本的语言,以便于计算机可以操作。很多与“ML”结尾的语言都是标记语言,比如:HTML,XML,XHTML,VML等等。标记语言与其他语言一样,也需要运行它们的环境,比如HTML的运行环境时浏览器,XML也要自己的解析和运行的环境。

基本结构:

<开始标签>标签体</结束标签> 

<name>out</name>

空标签:
<开始标签 属性名="属性值"/></结束标签>

<action path="/studentAction" type="org.lisen.mvc.action.StudentAction"></action>

<开始标签 属性名="属性值"/> 

<forward name="students" path="/students/studentList.jsp" redirect="false"/>

<br/><br/> 


二、自定义标签

🔘JSP标签库是什么?

是一个JSP标签集合,它封装了JSP应用的通用核心功能, 基于JSP标签我们可以理解为,是JSP应该通用功能的一种封装方式。

🔘JSP自定义标签生命周期

 实例化标签助手类之后就能调用doStartTag这个方法,随后查看这个方法的返回值,若这个返回值是EVAL_BODY_INCLUDE则说明其有标签体需要继续处理重新定义一个方法doAfterBody,查看该方法的返回值是否需要继续处理(返回值为EVAL_BODY_AGAIN再计算主体一次,EVAL PAGE计算页面的后续部分);若返回值是SKIP_BODY跳过主体进入结束标签,最后取消引用助手类。

了解助手类里面常量的意思

  1. SKIP_BODY跳过主体
  2. EVAL_BODY_INCLUDE:计算标签主体内容并[输出]
  3. EVAL_PAGE:计算页面的后续部分
  4. SKIP_PAGE跳过页面的后续部分
  5. EVAL_BODY_AGAIN:再计算主体一次

 🔘如何自定义标签

常见自定义标签主要步骤:

  • 编写助手类(继承BodyTagSupport)
  • 编写标签库描述文件(tld)
  • 在jsp页面上通过taglib指令导入标签库

注意:tld文件必须保存到WEB-INF目录或其子目录

 🔘标签类型

  1. UI标签:输出页面元素 如:Input、table
  2. 控制标签: 如if标签,foreach标签等
  3. 数据标签:用于向页面输入数据 如:out标签
  4. 空标签:如:br、hr

 🔘 开发示例

  •  out标签

1) 创建助手类

package com.zking.ml;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;

import com.mysql.jdbc.StringUtils;

public class OutTag extends BodyTagSupport{

    private String val;
	
	private String defaultVal;

	public String getVal() {
		return val;
	}

	public void setVal(String val) {
		this.val = val;
	}

	
	public String getDefaultVal() {
		return defaultVal;
	}

	public void setDefaultVal(String defaultVal) {
		this.defaultVal = defaultVal;
	}

	@Override
	public int doStartTag() throws JspException {
        //pageContext为页面上下文对象,用于和jsp共享数据
		JspWriter out = this.pageContext.getOut();
		try {
		if(StringUtils.isNullOrEmpty(val)) {
				out.println(this.defaultVal);
		}else {
			out.println(this.val);
		}
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		
		return SKIP_BODY;
	}
}

2) 编写tld文件,(必须放在WEB-INF目录或其目录下)

<!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>/zking</uri>

	<tag>
		<!-- 标签名 -->
		<name>out</name>
		<!-- 标签助手类 -->
		<tag-class>com.zking.ml.OutTag</tag-class>
		<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
		<body-content>empty</body-content>

		<attribute>
			<!-- 属性名, OutTag类中的val属性相匹配 -->
			<name>val</name>
			<!-- 表示该属性为必要的属性 -->
			<required>true</required>
			<!-- 该属性可以接受EL表示式的值 -->
			<rtexprvalue>true</rtexprvalue>
			<!-- 标签描述,用于说明标签的作用 -->
			<description>out标签</description>
		</attribute>

		<attribute>
			<!-- 属性名, OutTag类中的val属性相匹配 -->
			<name>defaultVal</name>
			<!-- 表示该属性为必要的属性 -->
			<required>false</required>
			<!-- 该属性可以接受EL表示式的值 -->
			<rtexprvalue>false</rtexprvalue>
			<!-- 标签描述,用于说明标签的作用 -->
			<description>out标签</description>
		</attribute>

	</tag>


</taglib>

3) 在页面上引入使用

若name没有设值则输出来的默认值为十一,下面代码name是设置了值的。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
   request.setAttribute("name", "苡桉");
%>
<z:out val="${name}" defaultVal="十一"/>

</body>
</html>

效果图如下:

  •  if标签

1)编写助手类

package com.zking.ml;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class IfTag extends BodyTagSupport{

	private boolean test;

	public boolean isTest() {
		return test;
	}

	public void setTest(boolean test) {
		this.test = test;
	}
	
	@Override
	public int doStartTag() throws JspException {
	  if(this.isTest()) {
		return EVAL_BODY_INCLUDE;
	}
		
		return SKIP_BODY;
	}
}

 2) tld文件,在tld中加入if标签的声明


	<tag>
		<name>if</name>
		<tag-class>com.zking.ml.IfTag</tag-class>
		<body-content>jsp</body-content>
		<description>if标签</description>
		<attribute>
			<name>test</name>
			<required>true</required>
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>

3) 在页面上使用

 若两值相等显示下面测试文字,反之则不显示

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- if -->
	<z:if test="${100 == 100}">
		测试if(100 == 100)
	</z:if>
	<z:if test="${100 == 1}">
	        测试if(100 == 1)
	</z:if>
</body>
</html>

 效果图如下:

 

  • foreach标签

1)编写助手类

package com.zking.ml;

import java.util.Iterator;
import java.util.List;
import java.util.Objects;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

@SuppressWarnings("serial")
public class ForeachTag extends BodyTagSupport{

	private List<?>items;
	private String var;
	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(Objects.isNull(this.items)||this.items.size()==0) {
			return SKIP_BODY;		
		}
		Iterator<?> it = this.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<?> it1 = (Iterator<?>)this.pageContext.getAttribute("it");
		if(it1.hasNext()) {
			this.pageContext.setAttribute(var, it1.next());
			return EVAL_BODY_AGAIN;
		}
		return SKIP_BODY;
	}
	
}

  2) tld文件,在tld中加入foreach标签的声明

     <tag>
     
     <name>foreach</name>
     <tag-class>com.zking.ml.ForeachTag</tag-class>
     <body-content>jsp</body-content>
     <description>foreach标签</description>
     
     <attribute>
     <name>items</name>
     <required>true</required>
     <rtexprvalue>true</rtexprvalue>
     </attribute>
     
     <attribute>
     <name>var</name>
     <required>true</required>
     <rtexprvalue>false</rtexprvalue>
     </attribute>
     </tag>

3) 在页面上使用

<%@page import="com.zking.ml.Book"%>
<%@page import="java.util.List"%>
<%@page import="com.zking.ml.TestData"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
	 //获取测试数据
	 List<Book>books=TestData.getBooks();
	  
	 //放入request对象中
	 request.setAttribute("books", books);
	%>
	<z:foreach items="${books}" var="b">
	${b.id }--${b.name }<br>
	</z:foreach>
	
	
</body>
</html>

效果图如下

 

  • select标签

1)编写助手类

package com.zking.ml;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;

import org.apache.commons.beanutils.BeanUtils;

import com.mysql.jdbc.StringUtils;

@SuppressWarnings("unused")
public class SelectTag extends BodyTagSupport{
private String id;
	
	private String name;
	
	private List<?> items;
	
	private String cssClass;
	
	private String cssStyle;
	
	private String value;
	
	private String text;
	
	private String selectValue;

	public void setText(String text) {
		this.text = text;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public void setSelectValue(String selectValue) {
		this.selectValue = selectValue;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setItems(List<?> items) {
		this.items = items;
	}

	public void setCssClass(String cssClass) {
		this.cssClass = cssClass;
	}

	public void setCssStyle(String cssStyle) {
		this.cssStyle = cssStyle;
	}
	
	@Override
		public int doStartTag() throws JspException {
			try {
				JspWriter out = this.pageContext.getOut();
				String html = getSelectHtml();
				out.print(html);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return SKIP_BODY;
		}
	
	private String getSelectHtml() throws Exception {
		
		StringBuilder sb = new StringBuilder();
		//构造页面需要的select元素
		sb.append("<select id="+id+"' name="+name+"'>");
		if(StringUtils.isNullOrEmpty(this.cssClass)) {
			sb.append("class='"+this.cssClass+"'");
		}
		
		if(StringUtils.isNullOrEmpty(this.cssClass)) {
			sb.append("style='"+this.cssStyle+"'");
		}
		
		sb.append(">");
		
		//循环生成options
		for(Object option:this.items) {
			String val = BeanUtils.getProperty(option, this.value);
			String txt = BeanUtils.getProperty(option, this.text);
			
			if(val.equals(this.selectValue)) {
				sb.append("<option value='"+val+"' selected>" + txt + "</option>");
			} else {
				sb.append("<option value='"+val+"' >" + txt + "</option>");
			}
		}
		
		
		
		sb.append("</select>");
		return sb.toString();
	}
	
}

  2) tld文件,在tld中加入select标签的声明


     <tag>
     <name>select</name>
     <tag-class>com.zking.ml.SelectTag</tag-class>
     <body-content>empty</body-content>
     <attribute>
        <name>id</name>
        <required>true</required>
        <rtexprvalue>false</rtexprvalue>
     </attribute>
     
      <attribute>
        <name>name</name>
        <required>true</required>
        <rtexprvalue>false</rtexprvalue>
     </attribute>
     
      <attribute>
        <name>items</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
     </attribute>
     
       <attribute>
        <name>cssClass</name>
        <required>false</required>
        <rtexprvalue>false</rtexprvalue>
     </attribute>
     
       <attribute>
        <name>cssStyle</name>
        <required>false</required>
        <rtexprvalue>false</rtexprvalue>
     </attribute>
     
       <attribute>
        <name>value</name>
        <required>true</required>
        <rtexprvalue>false</rtexprvalue>
     </attribute>
     
       <attribute>
        <name>text</name>
        <required>true</required>
        <rtexprvalue>false</rtexprvalue>
     </attribute>
     
       <attribute>
        <name>selectValue</name>
        <required>false</required>
        <rtexprvalue>false</rtexprvalue>
     </attribute>
     </tag>

3) 在页面上使用

<%@page import="com.zking.ml.Book"%>
<%@page import="java.util.List"%>
<%@page import="com.zking.ml.TestData"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
	 //获取测试数据
	 List<Book>books=TestData.getBooks();
	  
	 //放入request对象中
	 request.setAttribute("books", books);
	%>

	<select id="test" name="test" class="" style="width: 100px"> 
	<option value=0>已付款</option>
	<option value= selected>已发货</option>
	<option value=2>已签收</option>
	
	</select>
	
<z:select id="test" 
	   name="test" items="${books}" value="id"
	   text="name" selectValue="3"/>	
	
</body>
</html>

效果图如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值