一、自定义标签的作用
- 消除JSP中的java脚本,自定义标签也属于JSP中的一部分技术
- javax.servlet.jsp.tagext Tag接口,自定义标签处理类需要实现的接口Tag ;
- Tag接口的常量:
- EVAL_BODY_INCLUDE :为doStartTag服务,指示还要处理标签的主体内容。
- SKIP_BODY:为doStartTag服务,指示不处理开始标签后的主题内容
- EVAL_PAGE :为doEndTag签服务,指示还要处理结束标签后的内容
- SKIP_PAGE: 为doEndTag服务,指示不处理结束标签后的内容
- Tag接口的方法:所有d方法都是由容器创建,包括标签处理类的实例化也是由容器创建,但对于复杂的标签来说,只会创建一次实例,它的生命周期和servlet类似
- void setPageContext(PageContext pc):容器调用时,标签处理类实例化后,容器把PageContext对象传给调用者
- void setParent(Tag t) :设置父标签
- void doStartTag():遇到开始标签时,容器调用
- void doEndTag():遇到结束标签时,容器调用
- void replease():释放标签占用的资源,在服务停止或tomcat重启
- Tag getParent():获取父标签
二、自定义标签的开发步骤,快速入门,执行原理和过程
- 自定义标签的编写步骤:
- 编写java类实现 javax.servlet.jsp.tagext.Tag接口 或继承TagSupport 该类称为标签处理类 (对比:简单标签继承的是SimpleTagSupport)
- public class ShowRemoteIpTag extends TagSupport {
- public int doStartTag() throws JspException {
- String ip = pageContext.getRequest().getRemoteAddr();
- try {
- pageContext.getOut().write(ip);
- } catch (IOException e) {
- e.printStackTrace();
- }
- return super.doStartTag();
- }
- 在项目中新建一个.tld文件(文件怎么写参考tomcat中的tld文件),应注意的标签有short-name、uri、tag
- <?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>dsfds</description>
- <tlib-version>1.0</tlib-version>
- <short-name>itheima</short-name>
- <uri>http://www.itheima.com/jsp/tag</uri>
- <tag>
- <description>show remote ip</description>
- <name>showRemoteIp</name>
- <tag-class>com.itheima.tag.ShowRemoteIpTag</tag-class>
- <body-content>empty</body-content>
- </tag>
- </taglib>
- 在web.xml文件中配置tld的路径(这一步可选,前提是tld文件在WEB-INF目录下,则可不配置web.xml)
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <jsp-config>
- <taglib>
- <taglib-uri>http://www.itheima.com/jsp/tag</taglib-uri>
- <taglib-location>/WEB-INF/itheima.tld</taglib-location>
- </taglib>
- </jsp-config>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
- 在jsp页面中使用<%@ taglib uri="与tld中的uri对应" prefix="前缀名与tld中short-name对应"%>
- 编写java类实现 javax.servlet.jsp.tagext.Tag接口 或继承TagSupport 该类称为标签处理类 (对比:简单标签继承的是SimpleTagSupport)
- Tag标签的 执行原理和过程
- IE向容器请求带有自定义标签的jsp时,容器会找到标签处理类的映射路径,并根据路径初始化标签处理类(对于一个用户多次访问只初始化一次标签类),然后由容器调用setPageContext(PageContext pc)传入当前页面上下文对象、调用setParent(Tag t)传入父类标签,如果没有,传入null;需要注意的是,标签类实例化后就驻留内存了,生命周期与servlet类似,最后release方法在应用被卸载或tomcat重启时调用
三、自定义标签可以完成的功能
- 控制JSP页面的某一部分内容是否执行:在自定义标签类中,重写doStartTag()方法,return Tag.SKIP_BODY / EVAL_BODY_INCLUDE;
- 控制整个jsp页面是否执行: 在自定义标签类中,重写doEndTag()方法,return Tag.SKIP_PAGE / EVAL_PAGE;在页面头引用标签.
- 控制jsp页面重复执行: 在自定义标签类中,重写doStartTag和doAfterBody方法根据startTag返回值确定是否返回EVAL_BODY_AGAIN
- 修改页面输出内容: 自定义标签类继承BodyTagSupport类,得到getJspBody方法
- IterationTag接口:拓展了Tag接口的功能,增加了重复执行代码的方法,已知它的实现类TagSupport,我们只需继承TagSupport
- int doAfterBody():根据返回值来确定是否执行重复代码
- Tag.SKIP_BODY:指示忽略主题内容
- Iteration.EVAL_BODY_AGAIN:指示执行重复代码
- int doAfterBody():根据返回值来确定是否执行重复代码
- BodyTag接口:扩展了IterationTag接口的功能,提供获取主体内容的方法 ,已知它的实现类BodyTagSupport 我们只需继承BodyTagSupport
- int EVAL_BODY_BUFFERED:Request the creation of new buffer, a BodyContent on which to evaluate the body of this tag.
- void doInitBody() :容器来调用
- void setBodyContent(BodyContent b):b封装了主体内容。容器来调用
- 传统标签执行原理
- 初始化标签处理类后,调用setPageContext、setParent方法,根据标签类的doStartTag返回的值:>EVAL_BODY_INCLUDE、SKIP_BODY、EVAL_BODY_BUFERED来确定执行的方向;当返回值是EVAL_BODY_INCLUDE时,执行标签的主题内容,当返回值是EVAL_BODY_BUFFERED时执行BodyTagSupport中的doInitBody方法和setBodyContent方法,当返回值是SKIP_BODY时执行doEndTag方法
四、传统标签 && JSP中自定义标签核心类图
五、简单标签,执行原理和过程
- 原理:IE向容器请求带有自定义标签的jsp页面,初始化标签处理类,容器调用setJspContext传入当前页面上下文,接着调用setParent传入父类标签(如果有的话),然后容器调用setJspBody传入标签主体内容。最后还是由容器调用doTag执行处理
六、tld文件主要标签详解
- taglib:根元素 <%@ taglib uri="名称空间" prefix="短名称/前缀名"%>
- short-name:短名称,就是前缀名
- uri:绑定的名称空间
- tag:描述一个标签,在taglib下配置一个tag就相当于配置了一个标签
- name: 指示这个标签的名称是什么
- tag-class: 标签对应的类路径,包括包名和类名
- body-content: 指示是否包含主体内容,可选值有以下:
- empty:没有主体内容
- JSP:有主体内容,只服务于传统标签,jsp中出现的主体内容都能出现
- scriptless:有主体内容,只服务于简单标签,主体内容不能出现java脚本和EL表达式
- tagdependent:把主体内容原封不动的传递给标签处理类
- attribute:标签的属性,用于描述属性
- name:属性名称
- required:true|false|yes|no 该属性是不是必须的?
- rtexprvalue: true|false|yes|no 该属性的取值是否支持EL和java表达式
七、简单标签开发案例:
c:if
c:choose c:when c:otherwise==if else if
c:forEach
html标签转义