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标签。
希望能对你们有所帮助。
下篇文章见!