jsp自定义标签之详解


在这里插入图片描述

1. 自定义jsp标签的目的及意义

1.JSP标签是一种用于在JSP页面中引入自定义标签的技术

自定义JSP标签的目的是为了能够扩展JSP页面的功能,使开发人员能够将重复使用的功能封装为自定义标签,从而提高开发效率和代码的可读性。

2.自定义JSP标签的意义在于可以将页面上的代码逻辑与表示逻辑分离开来

,使得代码更加模块化,易于维护。同时,自定义标签也可以提高代码的重用性,减少了代码的重复编写,从而降低了代码编写的难度和工作量。自定义标签还可以使JSP页面的结构更加简洁,使业务逻辑更加清晰,提高web应用的可扩展性和可维护性。

3.总结

总的来说,自定义jsp标签的目的是为了简化JSP页面的编写,提高代码重用性,实现代码逻辑与表示逻辑分离,以及提高web应用的可扩展性和可维护性

2.标签语言的特点

1.前言

标签语言是一种用于描述文档结构和格式的语言。与传统的编程语言不同,标签语言通常不包含复杂的流程控制语句、函数定义等功能,而是主要用于定义页面或文档的结构和样式。以下是标签语言的一些主要特点:

2.标签式编码

标签式编码:标签语言采用标签式编码方式,通过使用标签及其属性来指示文档结构和样式,使得文档结构的维护更加方便和灵活。标签语言中的标签通常是用尖括号(<>)括起来的。

3.内嵌式编程

内嵌式编程:标签语言通常内嵌在其他语言或技术中,如HTML、CSS、JavaScript和JSP等,可以用于包含和连接到其他文件中。

4.专注于文档结构和样式

专注于文档结构和样式:标签语言主要用于描述文档结构和样式,如HTML用于描述网页结构、CSS用于描述网页样式。因此,标签语言通常不包含复杂的逻辑判断、循环等编程功能。

5.可静态生成或动态生成

可静态生成或动态生成:标签语言可以通过静态方式(如HTML页面)或动态方式(如通过服务器端生成)来生成文档和页面。

6.模块化开发

模块化开发:标签语言的标签可以分为不同的模块,可以组合和嵌套使用,从而使代码更加模块化和可复用。

总的来说,标签语言的主要特点是标签式编码、内嵌式编程、专注于文档结构和样式、可静态或动态生成,以及模块化开发。

3.自定义标签使用步骤

1.c标签与tld文件的关系

1.在JSP中,C标签库是用于访问上下文或者操作会话和请求的标签库。而TLD文件(Tag Library Descriptor)是JSP标签库的描述文件,用于描述标签库中所有标签和属性的信息。

2.C标签库与TLD文件有关系,因为在C标签库中,定义的标签和属性的信息都存储在TLD文件中。C标签库中的标签和属性只有在TLD文件中被定义后才能被使用。TLD文件描述了标签库中标签的名称、属性、标签体中可以包含的内容类型、标签的描述等信息。这些信息可以被容器用于编译和解析JSP页面。

3.当JSP编译器编译JSP页面时,它会检查所有使用的标签是否在TLD文件中定义,通过TLD文件中的信息来解析标签,从而生成相应的Java代码。在运行时,容器会根据TLD文件中描述的信息去处理标签库的相关标签。

4.总的来说,C标签库是用于访问上下文或者操作会话和请求的标签库,而TLD文件则是定义标签库中标签和属性信息的文件,C标签库中的标签和属性只有在TLD文件中被定义后才能被使用。TLD文件描述了标签的名称、属性、标签体中可以包含的内容类型、标签的描述等信息,容器可以根据TLD文件中描述的信息来解析标签,生成相应的Java代码,从而实现JSP页面的编译和解析。

2.尝试使用c标签的tld文件来创建自己的标签库

1.创建file文件,以.tld结尾。
2.把c标签的c.tld文件的内容复制到我刚刚创建的文件内。
3.在jsp文件内引入自己创建的tld文件
4.在jsp内测试下:

<%@ 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">
<%@ taglib uri="http://jsp.niyin.cn" prefix="z"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<z:if test="true">true</z:if>
<z:if test="false">false</z:if>
<z:set value="list" var="name"></z:set>
<z:out value="${name}"></z:out>
</body>
</html>

运行结果如下
在这里插入图片描述
说明我已经可以自己创建标签了。

3.自己编辑tld文件,定义标签

1.首先了解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">
    
  <description>JSTL 1.1 core library</description>
  <display-name>JSTL core</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>z</short-name>
  <uri>http://jsp.niyin.cn</uri>

  <validator>
    <description>
        Provides core validation features for JSTL tags.
    </description>
    <validator-class>
        org.apache.taglibs.standard.tlv.JstlCoreTLV
    </validator-class>
  </validator>

  <tag>
   <!--代表标签库的名字  -->
    <name>demo1</name>
    <!--该标签对应的的助手类的全路径名  -->
    <tag-class>com.niyin.tag.DemoTag1</tag-class>
    <!--  -->
    <body-content>JSP</body-content>
<!--     <attribute> -->
      <!--该 自定义jsp标签的属性名称-->
      <!--   <name>var</name> -->
        <!--该属性是否必填  -->
        <!-- <required>false</required> -->
        <!-- 该属性值是否支持表达式 -->
<!--         <rtexprvalue>false</rtexprvalue>
 -->    
<!--  </attribute>--> 
  </tag>
</taglib>
 

2.定义助手类

package com.niyin.tag;

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

/**
 * 
 * @author 匿瘾
 * 助手类
 *
 */
public class DemoTag1 extends BodyTagSupport {
@Override
public int doStartTag() throws JspException {
	System.out.println("doStartTag");
	return super.doStartTag();
}
	

@Override
	public int doAfterBody() throws JspException {
	System.out.println("doAfterBody");

	return super.doAfterBody();
	}
@Override
	public int doEndTag() throws JspException {
	System.out.println("doEndTag");
		return super.doEndTag();
	}


}

3.尝试测试以上代码

1.没有标签的

<%@ 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">
<%@ taglib uri="http://jsp.niyin.cn" prefix="z"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%-- <z:catch></z:catch> --%>
<z:demo1></z:demo1>
</body>
</html>

运行结果
在这里插入图片描述

2.有标签体的

<%@ 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">
<%@ taglib uri="http://jsp.niyin.cn" prefix="z"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%-- <z:catch></z:catch> --%>
<z:demo1>iji</z:demo1>
</body>
</html>

运行结果
在这里插入图片描述
现在已经完整的定义了一个jsp标签了。

4.jsp标签的生命周期

1.有标签体的情况下,默认调用dostarttage,doafterbody,doEndTag

2.如果将dostarttag的返回值改为skip_body,那么doafterbody就不会被执行。

package com.niyin.tag;

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

/**
 * 
 * @author 匿瘾
 * 助手类
 *
 */
public class DemoTag1 extends BodyTagSupport {
@Override
public int doStartTag() throws JspException {
	System.out.println("doStartTag");
//	return super.doStartTag();
	return skip_body ;

}
	

@Override
	public int doAfterBody() throws JspException {
	System.out.println("doAfterBody");

	return super.doAfterBody();
//	return EVAL_BODY_AGAIN;
//	
			
	
	}
@Override
	public int doEndTag() throws JspException {
	System.out.println("doEndTag");
		return super.doEndTag();
//	return SKIP_PAGE;
	}


}

运行结果
在这里插入图片描述

3.如果将dostarttage返回值改为EVAL_BODY_INCLUDE,doafterbody就会执行

package com.niyin.tag;

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

/**
 * 
 * @author 匿瘾
 * 助手类
 *
 */
public class DemoTag1 extends BodyTagSupport {
@Override
public int doStartTag() throws JspException {
	System.out.println("doStartTag");
//	return super.doStartTag();
	return EVAL_BODY_INCLUDE ;

}
	

@Override
	public int doAfterBody() throws JspException {
	System.out.println("doAfterBody");

	return super.doAfterBody();
//	return EVAL_BODY_AGAIN;
//	
			
	
	}
@Override
	public int doEndTag() throws JspException {
	System.out.println("doEndTag");
		return super.doEndTag();
//	return SKIP_PAGE;
	}


}

<%@ 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">
<%@ taglib uri="http://jsp.niyin.cn" prefix="z"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 有标签体的情况下,默认调用dostarttage,doafterbody,doEndTag
2.如果将dostarttag的返回值改为skip_body,
那么doafterbody就不会被执行。
3.如果将dostarttage返回值改为EVAL_BODY_INCLUDE,doafterbody就会执行
4.如果将doafterdoby返回值改为EVAL_BODY_AGAIN,直接进入死循环。
-->

<z:demo1>iji</z:demo1>
xx
</body>
</html>

在这里插入图片描述
并且输出了内容
在这里插入图片描述

4.如果将doafterdoby返回值改为EVAL_BODY_AGAIN,直接进入死循环。

package com.niyin.tag;

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

/**
 * 
 * @author 匿瘾
 * 助手类
 *
 */
public class DemoTag1 extends BodyTagSupport {
@Override
public int doStartTag() throws JspException {
	System.out.println("doStartTag");
	return super.doStartTag();
//	return EVAL_BODY_INCLUDE ;

}
	

@Override
	public int doAfterBody() throws JspException {
	System.out.println("doAfterBody");

//	return super.doAfterBody();s
	return EVAL_BODY_AGAIN;
//	
			
	
	}
@Override
	public int doEndTag() throws JspException {
	System.out.println("doEndTag");
		return super.doEndTag();
//	return SKIP_PAGE;
	}


}

<%@ 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">
<%@ taglib uri="http://jsp.niyin.cn" prefix="z"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 有标签体的情况下,默认调用dostarttage,doafterbody,doEndTag
2.如果将dostarttag的返回值改为skip_body,
那么doafterbody就不会被执行。
3.如果将dostarttage返回值改为EVAL_BODY_INCLUDE,doafterbody就会执行
4.如果将doafterdoby返回值改为EVAL_BODY_AGAIN,直接进入死循环。
-->

<z:demo1>iji</z:demo1>
xx
</body>
</html>

在这里插入图片描述
运行结果,控制台
在这里插入图片描述

5.使用SKIP_PAGE,会跳过后续内容

package com.niyin.tag;

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

/**
 * 
 * @author 匿瘾
 * 助手类
 *
 */
public class DemoTag1 extends BodyTagSupport {
@Override
public int doStartTag() throws JspException {
	System.out.println("doStartTag");
	return super.doStartTag();
//	return EVAL_BODY_INCLUDE ;

}
	

@Override
	public int doAfterBody() throws JspException {
	System.out.println("doAfterBody");

	return super.doAfterBody();
//	return EVAL_BODY_AGAIN;
//	
			
	
	}
@Override
	public int doEndTag() throws JspException {
	System.out.println("doEndTag");
//		return super.doEndTag();
	return SKIP_PAGE;
	}


}

<%@ 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">
<%@ taglib uri="http://jsp.niyin.cn" prefix="z"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 有标签体的情况下,默认调用dostarttage,doafterbody,doEndTag
2.如果将dostarttag的返回值改为skip_body,
那么doafterbody就不会被执行。
3.如果将dostarttage返回值改为EVAL_BODY_INCLUDE,doafterbody就会执行
4.如果将doafterdoby返回值改为EVAL_BODY_AGAIN,直接进入死循环。
-->

<z:demo1>iji</z:demo1>
xx
</body>
</html>

在这里插入图片描述
生命周期图,帮助你们理解。

在这里插入图片描述

5.自定义jsp标签实践

1.尝试自定义jsp if标签

助手类

package com.niyin.tag;

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 {
		// TODO Auto-generated method stub
		return test? EVAL_BODY_INCLUDE:SKIP_BODY;
	}
}

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">
    
  <description>JSTL 1.1 core library</description>
  <display-name>JSTL core</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>z</short-name>
  <uri>http://jsp.niyin.cn</uri>

  <validator>
    <description>
        Provides core validation features for JSTL tags.
    </description>
    <validator-class>
        org.apache.taglibs.standard.tlv.JstlCoreTLV
    </validator-class>
  </validator>

  <tag>
   <!--代表标签库的名字  -->
    <name>demo</name>
    <!--该标签对应的的助手类的全路径名  -->
    <tag-class>com.niyin.tag.DemoTag1</tag-class>
    <!--  -->
    <body-content>JSP</body-content>
    <attribute>
      <!--该 自定义jsp标签的属性名称-->
        <name>var</name>
        <!--该属性是否必填  -->
        <required>false</required>
        <!-- 该属性值是否支持表达式 -->
        <rtexprvalue>false</rtexprvalue>
    </attribute>
  </tag>
  
   <tag>
  
    <name>if</name>
 
    <tag-class>com.niyin.tag.Iftag</tag-class>
    
    <body-content>JSP</body-content>
    <attribute>
        <name>test</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>
</taglib>
 

jsp页面内测试

<%@ 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">
<%@ taglib uri="http://jsp.niyin.cn" prefix="z"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 有标签体的情况下,默认调用dostarttage,doafterbody,doEndTag
2.如果将dostarttag的返回值改为skip_body,
那么doafterbody就不会被执行。
3.如果将dostarttage返回值改为EVAL_BODY_INCLUDE,doafterbody就会执行
4.如果将doafterdoby返回值改为EVAL_BODY_AGAIN,直接进入死循环。
-->

<%-- <z:demo1>iji</z:demo1> --%>
xx
<z:if test="true">true</z:if>
<z:if test="flase">false</z:if>

</body>
</html>

运行结果
在这里插入图片描述

2.尝试定义jsp set与out标签

set助手类

package com.niyin.tag;

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 {
pageContext.setAttribute(var, value);

		return super.doStartTag();
	}
	
}

out助手类

package com.niyin.tag;

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 {
JspWriter out = pageContext.getOut();
   try {
	out.print(value);
} catch (IOException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}
	return super.doStartTag();
	}
}

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">
    
  <description>JSTL 1.1 core library</description>
  <display-name>JSTL core</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>z</short-name>
  <uri>http://jsp.niyin.cn</uri>

  <validator>
    <description>
        Provides core validation features for JSTL tags.
    </description>
    <validator-class>
        org.apache.taglibs.standard.tlv.JstlCoreTLV
    </validator-class>
  </validator>

  <tag>
   <!--代表标签库的名字  -->
    <name>demo</name>
    <!--该标签对应的的助手类的全路径名  -->
    <tag-class>com.niyin.tag.DemoTag1</tag-class>
    <!--  -->
    <body-content>JSP</body-content>
    <attribute>
      <!--该 自定义jsp标签的属性名称-->
        <name>var</name>
        <!--该属性是否必填  -->
        <required>false</required>
        <!-- 该属性值是否支持表达式 -->
        <rtexprvalue>false</rtexprvalue>
    </attribute>
  </tag>
  
   <tag>
  
    <name>out</name>
 
    <tag-class>com.niyin.tag.outtag</tag-class>
    
    <body-content>JSP</body-content>
    <attribute>
        <name>value</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>
  
  <tag>
  
    <name>set</name>
 
    <tag-class>com.niyin.tag.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>false</rtexprvalue>
    </attribute>
  </tag>
  
</taglib>
 

测试代码

<%@ 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">
<%@ taglib uri="http://jsp.niyin.cn" prefix="z"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 有标签体的情况下,默认调用dostarttage,doafterbody,doEndTag
2.如果将dostarttag的返回值改为skip_body,
那么doafterbody就不会被执行。
3.如果将dostarttage返回值改为EVAL_BODY_INCLUDE,doafterbody就会执行
4.如果将doafterdoby返回值改为EVAL_BODY_AGAIN,直接进入死循环。
-->

<%-- <z:demo1>iji</z:demo1> --%>
xx
<%-- <z:if test="true">true</z:if>
<z:if test="flase">false</z:if> --%>

<z:set var="name" value="nihao"></z:set>
<z:out value="${name }"></z:out>
</body>
</html>

运行结果
在这里插入图片描述
说明,已经成功定义了set与out标签。
希望能对你们有所帮助。
下篇文章见!

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值