自定义标签

1.什么是自定义标签?

用户定义的一种自定义的jsp标记 。当一个含有自定义标签的jsp页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为 标签处理类 的对象的操作。于是,当jsp页面被jsp引擎转化为servlet后,实际上tag标签被转化为了对tag处理类的操作。 

2.导入JSTL标签库:

通过JSTL标签遍历集合元素

<%@page import="com.zhaoliang.tag.Customer"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 导入JSTL标签库,注意:如果没有 /jsp 会出现  XXX does not support runtime expressions-->
<%@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=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<!-- 遍历customers中元素,并打印name和age -->
	<c:forEach items="${requestScope.customers }" var="customer">
		--${customer.name },${customer.age }<br>
	</c:forEach>
</body>
</html>

<%@page import="com.zhaoliang.tag.Customer"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!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=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<%
		//模拟Servlet中的操作
		List<Customer> customers = new ArrayList<Customer>();
		customers.add(new Customer("AA",11));
		customers.add(new Customer("BB",12));
		customers.add(new Customer("CC",13));
		
		request.setAttribute("customers", customers);
	%>
	
	<jsp:forward page="testtag.jsp"></jsp:forward>	
</body>
</html>

3.标签库介绍:

1)接口和类之间的关系



2)自定义标签分类:

(1)空标签:<hello/>
(2)带有属性的空标签:
   <max num1=“3” num2=“5”/>
(3)带有内容的标签:
  <greeting>
     hello
  </greeting>
(4)带有内容和属性的标签:
  <greeting name=“Tom”>
    hello
  </greeting>

3)自定义标签

(1)开发自定义标签,其核心就是要编写处理器类,一个标签对应一个标签处理器类,而一个标签库则是很多标签处理器的集合。所有的标签处理器类都要实现 JspTag 接口,该接口中没有定义任何方法,主要作为 Tag 和 SimpleTag 接口的父接口。

(2)开发自定义标签的步骤:①编写完成标签功能的 Java 类(标签处理器)   ②编写标签库描述(tld)文件,在tld文件中对自定义中进行描述    ③在 JSP 页面中导入和使用自定义标签

(3)标签类中方法介绍


4)自定义空标签:<hello/>

(1)编写标签处理类(HelloSimpleTag):该类实现了 SimpleTag 接口

import java.io.IOException;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;


public class HelloSimpleTag implements SimpleTag {


<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public void doTag() throws JspException, IOException {
<span style="white-space:pre">		</span>pageContext.getOut().print("hello");
<span style="white-space:pre">		</span>HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
<span style="white-space:pre">		</span>pageContext.getOut().print("hello : " + request.getParameter("name"));
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public JspTag getParent() {
<span style="white-space:pre">		</span>// TODO Auto-generated method stub
<span style="white-space:pre">		</span>return null;
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public void setJspBody(JspFragment arg0) {
<span style="white-space:pre">		</span>// TODO Auto-generated method stub


<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>private PageContext pageContext;
<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public void setJspContext(JspContext arg0) {
<span style="white-space:pre">		</span>this.pageContext = (PageContext)arg0;
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public void setParent(JspTag arg0) {
<span style="white-space:pre">		</span>// TODO Auto-generated method stub


<span style="white-space:pre">	</span>}


}
(2)编写标签库描述文件(*.tld)

<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">
    
  <!-- 描述TLD文件 -->
  <description>MyTag 1.0 core library</description>
  <display-name>MyTag core</display-name>
  <tlib-version>1.0</tlib-version>
  
  <!-- 建议在 JSP 页面上使用的标签的前缀 -->
  <short-name>tagZ</short-name>
  
  <!-- 作为TLD 文件的ID,用来唯一标识当前的 TLD 文件,多个TLD 文件的 URI 不能重复,
  	   通过JSP页面的 taglib 标签的 uri 属性来引用 -->
  <uri>http://www.haha.com/mytag/core</uri>
  
  <!-- 描述自定义的 HelloSimpleTag 标签 -->
  <tag>
  	<!-- 标签的名称 -->
  	<name>hello</name>
  	
  	<!-- 标签对应类的全类名 -->
  	<tag-class>com.haha.tag.HelloSimpleTag</tag-class>
  	
  	<!-- 标签体类型 -->
  	<body-content>empty</body-content>
  </tag>  
</taglib>
(3)在JSP 页面导入标签库

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
 
<!-- 导入标签库(描述文件) -->
<%@ taglib prefix="tagz" uri="http://www.zhaoliang.com/mytag/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=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	
	<tagz:hello/>
	
</body>
</html>

5)自定义带有属性的空标签:
   <max num1=“3” num2=“5”/>

(1)在标签处理类中定义 XXX 属性和 setXXX() 方法

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;

public class HelloSimpleTag implements SimpleTag {
	
	private String value;
	private int count;
	
	public void setValue(String value) {
		this.value = value;
	}
	
	public void setCount(int count) {
		this.count = count;
	}

	@Override
	public void doTag() throws JspException, IOException {
		
		pageContext.getOut().print(count + " : " + value);
		pageContext.getOut().print("<br>");
				
		HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
		pageContext.getOut().print("hello : " + request.getParameter("name"));
	}

	@Override
	public JspTag getParent() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setJspBody(JspFragment arg0) {
		// TODO Auto-generated method stub

	}
	
	private PageContext pageContext;
	@Override
	public void setJspContext(JspContext arg0) {
		this.pageContext = (PageContext)arg0;
	}

	@Override
	public void setParent(JspTag arg0) {
		// TODO Auto-generated method stub

	}

}
(2)在TLD描述文件中对标签进行描述

<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">
    
  <!-- 描述TLD文件 -->
  <description>MyTag 1.0 core library</description>
  <display-name>MyTag core</display-name>
  <tlib-version>1.0</tlib-version>
  
  <!-- 建议在 JSP 页面上使用的标签的前缀 -->
  <short-name>tagZ</short-name>
  
  <!-- 作为TLD 文件的ID,用来唯一标识当前的 TLD 文件,多个TLD 文件的 URI 不能重复,
  	   通过JSP页面的 taglib 标签的 uri 属性来引用 -->
  <uri>http://www.zhaoliang.com/mytag/core</uri>
  
  <!-- 描述自定义的 HelloSimpleTag 标签 -->
  <tag>
  	<!-- 标签的名称 -->
  	<name>hello</name>
  	
  	<!-- 标签对应类的全类名 -->
  	<tag-class>com.zhaoliang.tag.HelloSimpleTag</tag-class>
  	
  	<!-- 标签体类型 -->
  	<body-content>empty</body-content>
  	
  	<!-- 描述当前标签的属性 -->
  	<attribute>
  		<!-- 属性名 -->
  		<name>value</name>
  		<!-- 该属性是否是必须的 -->
  		<required>true</required>
  		<!-- rtexprvalue : runtime expression value 
  			当前属性是否接受运行时表达式的动态值 -->
  		<rtexprvalue>true</rtexprvalue>
  	</attribute>
  	
  	<attribute>
  		<name>count</name>
  		<required>false</required>
  		<rtexprvalue>true</rtexprvalue>
  	</attribute>
  </tag>  
</taglib>
(3)使用标签

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
 
<!-- 导入标签库(描述文件) -->
<%@ taglib prefix="tagz" uri="http://www.zhaoliang.com/mytag/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=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	
	<tagz:hello value="${param.name }" count="${param.count }" />
	
</body>
</html>
6)带有内容的标签:
  <greeting>
       hello
  </greeting>

(1)若标签中含有标签体,则在标签处理器中使用 JspFragment 对象封装标签体信息

(2)若标签含有标签体,则 JSP 引擎会调用 setJspBody() 方法把 JspFragment  对象传给标签处理器。在SimpleTagSupport 中还定义了一个 getJspBody() 方法用于返回 JspFragment  对象

(3)JspFragment  的 invoke(Writer) 方法:把标签体内容从Writer中输出,若为null,则等同于invoke(getJspContext().getOut()),即直接把标签体内容输出到页面上。

(4)在TLD 文件中,使用<body-content>来描述标签体类型,取值:

①empty:没有标签体
scriptless:标签体可以包含 el 表达式和 JSP 动作元素,但不能包含 JSP 的脚本元素
③tagdependent:表示标签体交由标签本身去解析处理。若指定 tagdependent,在标签体中的所有代码都会原封不动的交给标签处理器,而不是将执行结果传递给标签处理器

练习:自定义带有属性和标签体的标签:将标签体的内容转换为大写,并输出time次

处理器类(TestFragment)

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class TestFragment extends SimpleTagSupport {

	private int time;
	public void setTime(int time) {
		this.time = time;
	}
	@Override
	public void doTag() throws JspException, IOException {
		//1.得到标签体内容
		JspFragment bodycontent = getJspBody();
		StringWriter sw = new StringWriter();
		bodycontent.invoke(sw);
		String content = sw.toString();
		
		//2.将标签体内容转换成大写
		content.toUpperCase();
		
		//3.循环输出
		for(int i = 0;i < time;i++){
			getJspContext().getOut().print(content);
			getJspContext().getOut().print("<br>");
		}
		
	}
}
配置TLD

  <tag>
	<name>toUperCase</name>
	<tag-class>com.javalearning.tag.TestFragment</tag-class>
	<body-content>scriptless</body-content>
	
	<attribute>
		<name>time</name>
		<required>true</required>
		<rtexprvalue>true</rtexprvalue>
	</attribute>
  </tag>
测试

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
    
<%@ taglib prefix="tag" uri="http://www.java.com/mytag_1/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=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

		<tag:toUperCase time="5">zhaoliang</tag:toUperCase>
		
</body>
</html>

练习:模拟forEach标签

编写标签处理器

import java.io.IOException;
import java.util.List;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

import org.apache.catalina.connector.Request;

public class ListIteratorWithBody extends SimpleTagSupport {
	private List lists;
	private String var;
	
	public void setLists(List lists) {
		this.lists = lists;
	}
	public void setVar(String var) {
		this.var = var;
	}
	
	@Override
	public void doTag() throws JspException, IOException {
		
		if(lists != null){
			for(Object obj : lists){
				getJspContext().setAttribute(var, obj);
				getJspBody().invoke(null);
			}
		}
		
	}
}
配置 TLD 文件

  <tag>
  	<name>forEach</name>
  	<tag-class>com.javalearning.tag.ListIteratorWithBody</tag-class>
  	<body-content>scriptless</body-content>
  	
  	<attribute>
  		<name>lists</name>
  		<required>true</required>
  		<rtexprvalue>true</rtexprvalue>
  	</attribute>
  	<attribute>
  		<name>var</name>
  		<required>true</required>
  		<rtexprvalue>true</rtexprvalue>
  	</attribute>
  </tag>
测试

		<%
			List<Customer> lists = new ArrayList<Customer>();
			lists.add(new Customer("AA",12));
			lists.add(new Customer("BB",13));
			lists.add(new Customer("CC",14));
			
			request.setAttribute("lists", lists);
			
		%>
		
		<tag:forEach lists="${requestScope.lists }" var="cust">
			${cust.name }--${cust.age }
		</tag:forEach>	

7)带有父标签的标签:

 <greeting name=“Tom”>
       hello
  </greeting>

(1)父标签无法获取子标签的引用,父标签仅把子标签当作标签体来使用

(2)子标签可以通过 getParent() 方法来引用父标签(需要继承 SimpleTagSupport 类或者实现 SimpleTag 接口的该方法):若子标签的确有父标签,JSP 会把带有父标签的引用通过  setParent(JspTag parent) 来赋给标签处理器

(3)由于父标签类型为 JspTag 类型,该接口是一个空接口,用来统一 SimpleTag 和 Tag 的,实际使用需要进行类型的强制转换。

(4)在TLD 文件中,不需要为父标签进行额外的配置,但子标签是以标签体存在的,所以父标签的:<body-content>scriptless</body-content>


练习:

		<%--
			1.开发3个标签:choose when otherwise
			2.其中when标签有一个boolean类型的属性:test
			3.choose是when和otherwise的父标签,when在otherwise之前使用
			4.在父标签choose中定义一个“全局”的 boolean 类型变量 flag :
			     用于判断子标签在满足条件的情况下是否执行
			  1)若 when 的 test 为 true,且 when 父标签的 flag 也为 true,则执行 when 的标签体,并将 flag 置为 false
			  2)若 when 的 test 为 true,且 when 父标签的 flag 为 false,则不执行 when 的标签体
			  3)若 flag 为 true,otherwise执行标签体
		--%>
		
		<tag:choose>
			<tag:when test="${param.age > 22}">大学毕业</tag:when>
			<tag:when test="${param.age > 18}">高中毕业</tag:when>
			<tag:otherwise>高中以下...</tag:otherwise>
		</tag:choose>

(1)编写choose标签处理器

import java.io.IOException;

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

public class ChooseTag extends SimpleTagSupport {
	
	private boolean flag = true;
	
	public void setFlag(boolean flag) {
		this.flag = flag;
	}
	
	public boolean isFlag() {
		return flag;
	}
	
	@Override
	public void doTag() throws JspException, IOException {
		getJspBody().invoke(null);
	}
}
(2)编写when标签处理器

import java.io.IOException;

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

public class WhenTag extends SimpleTagSupport {
	
	private boolean test;
	
	public void setTest(boolean test) {
		this.test = test;
	}
	
	@Override
	public void doTag() throws JspException, IOException {
		
		if(test){
			ChooseTag chooseTag = (ChooseTag)getParent();
			boolean flag = chooseTag.isFlag();
			if(flag){
				getJspBody().invoke(null);
				chooseTag.setFlag(false);
			}
		}
	}
}
(3)编写otherwise标签处理器

import java.io.IOException;

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

public class OtherwiseTag extends SimpleTagSupport {
	@Override
	public void doTag() throws JspException, IOException {
		ChooseTag chooseTag = (ChooseTag)getParent();
		if(chooseTag.isFlag()){
			getJspBody().invoke(null);
		}
	}
}
(4)配置标签

  <tag>
  	<name>choose</name>
  	<tag-class>com.javalearning.tag.ChooseTag</tag-class>
  	<body-content>scriptless</body-content>
  </tag>
  
  <tag>
  	<name>when</name>
  	<tag-class>com.javalearning.tag.WhenTag</tag-class>
  	<body-content>scriptless</body-content>
  	<attribute>
  		<name>test</name>
  		<required>true</required>
  		<rtexprvalue>true</rtexprvalue>
  	</attribute>
  </tag>
  
  <tag>
  	<name>otherwise</name>
  	<tag-class>com.javalearning.tag.OtherwiseTag</tag-class>
  	<body-content>scriptless</body-content>
  </tag>
(5)测试

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="tag" uri="http://www.java.com/mytag_1/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>
	
		
		<%--
			1.开发3个标签:choose when otherwise
			2.其中when标签有一个boolean类型的属性:test
			3.choose是when和otherwise的父标签,when在otherwise之前使用
			4.在父标签choose中定义一个“全局”的 boolean 类型变量 flag :
			     用于判断子标签在满足条件的情况下是否执行
			  1)若 when 的 test 为 true,且 when 父标签的 flag 也为 true,则执行 when 的标签体,并将 flag 置为 false
			  2)若 when 的 test 为 true,且 when 父标签的 flag 为 false,则不执行 when 的标签体
			  3)若 flag 为 true,otherwise执行标签体
		--%>
		
		<tag:choose>
			<tag:when test="${param.age > 22}">大学毕业</tag:when>
			<tag:when test="${param.age > 18}">高中毕业</tag:when>
			<tag:otherwise>高中以下...</tag:otherwise>
		</tag:choose>
		
</body>
</html>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis自定义标签是指在使用MyBatis框架时,用户可以根据自己的需求自定义一些标签来简化SQL映射文件的编写和配置。通过自定义标签,可以使SQL映射文件的结构更加清晰,提高代码的可读性和可维护性。 在MyBatis中,自定义标签主要涉及到两个方面:自定义SQL标签和自定义参数标签。 自定义SQL标签可以用来封装通用的SQL逻辑,例如逻辑删除的标记、多条件查询等。通过自定义标签,可以将这些通用的SQL逻辑封装到一个复用的标签中,然后在SQL映射文件中直接引用这个标签,从而减少代码的重复编写。这样一来,我们只需要在需要使用这个通用SQL逻辑的地方写上自定义标签的名称即可,大大简化了SQL映射文件的编写和维护。 自定义参数标签可以用来封装通用的参数逻辑,例如分页查询、排序等。通过自定义标签,可以将这些通用的参数逻辑封装到一个复用的标签中,然后在SQL映射文件中直接引用这个标签,从而减少参数的重复配置。这样一来,我们只需要在需要使用这个通用参数逻辑的地方写上自定义标签的名称即可,大大简化了SQL参数的配置。 总之,MyBatis自定义标签的作用是简化SQL映射文件的编写和配置,并提高代码的可读性和可维护性。通过自定义标签,我们可以将通用的SQL逻辑和参数逻辑封装起来,然后在SQL映射文件中直接引用这些标签,从而减少重复编写和配置。这样一来,我们可以更加专注于业务逻辑的编写,而不用关心繁琐的SQL和参数配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值