jsp自定义标签

为什么要自定义开发标签

相信很多人很好奇为啥有现成的标签库,还要去自定义开发标签,举个例子:我们在jsp使用修改时,传值给界面单选按钮是否选中,是这样的:

<c:if test="${ name=='男' }">
<input type="radio" checked="checked" value="男">
</c:if>

那如果是爱好类型的复选框呢?爱好有几百种,打个比方,那页面上就全是标签代码了,所以,了解掌握自定义标签开发出适合自己项目的标签,可以减少多余的代码,页面更加直观简洁

标签的语言特点

我们比较常用的标签就是jstl标准标签库---->c标签,我们自定义jsp标签是在此基础上,开发出符合自己的标签使用,它有哪些语言特点,下面带大家看看:

  1. <开始标签 属性="属性值">标签体</结束标签>
  2. 空标签 : <br/><hr/> <开始标签></结束标签> <开始标签/>

标签的类型

标签的类型大概有三种:

  1. ui标签,例如:<c:out value=""></c:out>
  2. 控制标签,例如:<c:if test="">标签体</c:if>
  3. 数据标签,例如自定义的数据显示标签:<x:select/>,c标签的<c:set var="" value=""></c:set>

开发和使用步骤

  1. 第一:

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

例如自定义一个<x:if test=" ">标签体</c:if>标签:

package com.xiaoyang;

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;
	}
}

  1. 第二:

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

我自定义这个标签的tld配置:

<tag>
		<name>if</name>//标签名
		<tag-class>com.xiaoyang.IfTag</tag-class>//助手类路径
		<body-content>JSP</body-content>
		<attribute>//属性
			<name>test</name>//属性名
			<required>true</required>//是否为必填项
			<rtexprvalue>true</rtexprvalue>//是否支持表达式
		</attribute>
	</tag>

然后把文件放在:
在这里插入图片描述
3.第三:

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

从我们常用的·jstl核心标签库开始入手:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

在这里插入图片描述
如上,我们在使用c标签库时,不仅要导入jar包,还要在页面引入一行代码。接下来点击uri地址,我们可以看到:

 <description>JSTL 1.1 core library</description>
  <display-name>JSTL core</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>c</short-name>
  <uri>http://java.sun.com/jsp/jstl/core</uri>

这里的<short-name>c</short-name> 就是我们在页面引入时的prefix="c",<uri>http://java.sun.com/jsp/jstl/core</uri>就是页面引入的uri="http://java.sun.com/jsp/jstl/core" %>
看完c标签的引入方式后,那么,我们自定义标签也可以这样配置tld:

<description>JSTL 1.1 core library</description>
	<display-name>JSTL core</display-name>
	<tlib-version>1.1</tlib-version>
	<short-name>x</short-name>
	<uri>/xiaoyang</uri>

在页面引入:

<%@taglib prefix="x" uri="/xiaoyang" %>
自定义标签的生命周期

在完成上面的步骤后,开发自定义标签,还必须要掌握它的生命周期的流转:

标签的几个生命阶段:

  1. doStartTag()

对应的阶段方法有:SKIP_BODY(跳过主体)、EVAL_BODY_INCLUDE(计算主体内容并输出)

  1. doEndTag()

对应的阶段方法:EVAL_PAGE(计算页面后续内容)、SKIP_PAGE(跳过页面后续内容)

  1. doAfterBody()

对应的阶段方法:EVAL_BODY_AGAIN(再次计算主体)、EVAL_PAGE(计算页面后续内容)

如图:
在这里插入图片描述

案例结合

了解完自定义标签的开发和使用步骤以及它的一个生命周期后,我们结合一个案例,更好的去了解它,这里我自定义开发了x:out、x:foreach、x:if、x:set

首先看x:if:
在开发时,首先仿照c:if分析:
在这里插入图片描述

那么我们就可以开始编码了:
首先是助手类:

package com.xiaoyang;

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 {
		//如果为真则计算主体输出,否则跳过主体
		return test ? EVAL_BODY_INCLUDE:SKIP_BODY;
	}
	
}

然后在tld文件中配置好:

<tag>
		<name>if</name>
		<tag-class>com.xiaoyang.IfTag</tag-class>
		<body-content>JSP</body-content>
		<attribute>
			<name>test</name>
			<required>true</required>
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>

然后我们页面引入tld文件后,就可以使用了:

<x:if test="true"></x:if>
<x:if test="false"></x:if>

输出结果:
在这里插入图片描述
然后是x:out、x:set标签,一样的套路,参照c标签分析:
在这里插入图片描述在这里插入图片描述
x:out助手类:

package com.xiaoyang;

import java.io.IOException;

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

public class OutTag extends BodyTagSupport{

	
	private Object value;//内容

	public Object getValue() {
		return value;
	}

	public void setValue(Object value) {
		this.value = value;
	}
	
	@Override
	public int doStartTag() throws JspException {
		//out标签直接输出value内容
		JspWriter out = pageContext.getOut();
		try {
			out.print(value);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return SKIP_BODY;
	}
}

tld配置

<tag>
		<name>out</name>
		<tag-class>com.xiaoyang.OutTag</tag-class>
		<body-content>JSP</body-content>
		<attribute>
			<name>value</name>
			<required>true</required>
			<rtexprvalue>true</rtexprvalue>
			<type>boolean</type>
		</attribute>
	</tag>

x:set助手类:

package com.xiaoyang;

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

public class SetTag extends BodyTagSupport{

	private String var;//属性,相当于键
	private Object value;//内容
	public String getVar() {
		return var;
	}
	public void setVar(String var) {
		this.var = var;
	}
	public Object getValue() {
		return value;
	}
	public void setValue(Object value) {
		this.value = value;
	}
	
	
	@Override
	public int doStartTag() throws JspException {
		//存入页面,以var作为键,存入值value
		pageContext.setAttribute(var, value);
		return SKIP_BODY;
	}
	
}

tld配置

<tag>
		<name>set</name>
		<tag-class>com.xiaoyang.SetTag</tag-class>
		<body-content>JSP</body-content>
		<attribute>
			<name>var</name>
			<required>true</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		<attribute>
			<name>value</name>
			<required>true</required>
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>

调用:

<x:set var="sex" value="男"></x:set>
 <x:out value="${sex }"></x:out> 

结果:
在这里插入图片描述

最后就是x:foreach标签了:
在这里插入图片描述
助手类:

package com.xiaoyang;

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 String var;//保存当前数据到作用域的一个键
	private List<Object> items;//数据源
	public String getVar() {
		return var;
	}
	public void setVar(String var) {
		this.var = var;
	}
	public List<Object> getItems() {
		return items;
	}
	public void setItems(List<Object> items) {
		this.items = items;
	}
	
	@Override
	public int doStartTag() throws JspException {
        if(items==null||items.size()==0) {//如果数据源为空,跳过主体,不执行遍历
        	return SKIP_BODY;
        }
        //有数据则取值
        Iterator<Object> iterator = items.iterator();
        Object next = iterator.next();
        pageContext.setAttribute(var, next);
        //将剩下的值存入作用域
        pageContext.setAttribute("ite", iterator);
		return EVAL_BODY_INCLUDE;
	}
	
	@Override
	public int doAfterBody() throws JspException {
		//取出作用域剩余的值
		Iterator<Object> attribute =(Iterator<Object>)pageContext.getAttribute("ite");
		//迭代遍历
	    while(attribute.hasNext()) {
	    	pageContext.setAttribute(var, attribute.next());
	    	return EVAL_BODY_AGAIN;
	    }
	    //遍历完计算页面后续内容
		return EVAL_PAGE;
	}
}

配置tld:

<tag>
		<name>foreach</name>
		<tag-class>com.xiaoyang.ForeachTag</tag-class>
		<body-content>JSP</body-content>
		<attribute>
			<name>var</name>
			<required>true</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		<attribute>
			<name>items</name>
			<required>true</required>
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>

调用:

<%
List<String> ls=new ArrayList<String>();
ls.add("1");
ls.add("2");
request.setAttribute("ls", ls);
%>
<x:foreach items="${ls }" var="a">
${a }
</x:foreach>

结果:
在这里插入图片描述

尾言

搞定,溜了溜了…

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值