一. 自定义标签的开发步骤
1、编写一个类实现Tag接口。这个类就称之为标签处理类
TagSupport实现了Tag接口。
public class ShowRemoteIpTag extendsTagSupport{
@Override
publicint doStartTag() throws JspException {
Stringip = pageContext.getRequest().getRemoteAddr();
JspWriterout = pageContext.getOut();
try {
out.write(ip);
}catch (IOException e) {
e.printStackTrace();
}
returnsuper.doStartTag();
}
}
2、在WEB-INF目录下建立一个扩展名为tld的xml文件。(Tomcat找)
<?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/j2eehttp://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>itheima</short-name>
<uri>http://www.itheima.com/jsp/tag</uri>
<tag>
<description>Showremote ip</description>
<name>showRemoteIp</name>
<tag-class>com.itheima.tag.ShowRemoteIpTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
3、在web.xml中对tld文件中的uri和tld文件的实际存储位置进行对应配置(可选的)
<jsp-config>
<taglib>
<taglib-uri>http://www.itheima.com/jsp/tag</taglib-uri>
<taglib-location>/WEB-INF/itheima.tld</taglib-location>
</taglib>
</jsp-config>
4、 在JSP中通过taglib指令引入标签库
二. TLD标签的主要元素
taglib:
short-name:引用的名称空间
uri:唯一的uri地址,没有实际意义。同xmlschema的uri一样
tlib-version:版本号。新建的东东1.0
tag:描述一个标签
name:标签名
tag-class:标签处理类。全类名
body-content:主体内容的类型
可选值:
empty:没有主体内容。传统和简单标签都可以用
JSP:有主体内容。传统标签使用(html,el,java脚本,java表达式。凡是jsp中可以出现的都可以作为主体内容)
scriptless:有主体内容。简单标签使用。(html,el。与JSP不同的是,主体内容不能出现java脚本或表达式)
tagdepentend:是否将主体内容当做字符串处理。
attribute:描述标签的一个属性
name:属性名称
required:是否是必须的属性.true|false
rtexprvalue:属性取值是否支持表达式(EL或Java 表达式runtimeexpression value)
二. 传统标签: 标签类的生命周期与Servlet一样.
JspTag接口
Tag接口: 继承于JspTag
EVAL_BODY_INCLDE:返回此属性,会直接执行doAfterBody方法,不会去执行doinitBody方法和setBodyContent方法,设置在doStartTag方法.
EVAL_PAGE:会执行后面的内容.设置在doEndTag方法
SKIP_BODY:跳过主体内容,设置在doStratTag方法
SKIP_PAGE:跳过标签后的页面内容,在doEngTag方法
IterationTag接口:继承于Tag
EVAL_BODY_AGAIN:重复执行doAfterBody方法.
BodyTag接口:继承于IterationTag
EVAL_BODY_BUFFRED:在doStartTag方法上,返回此值,就会去执行doinitBody方法和setBodyContent方法,后面就可以拿到BodyContent对象.可以获取主体的内容.然后再执行doAfterBody方法.
EVAL_BODY_TAG:无用,过时
TagSupport类:实现于IterationTag接口
BodyTagSupport类:实现于BodyTag接口,继承于TagSupport类,如果需要拿到主体的内容,主继承此类,此类可以拿到bodyContent对象,toString方法拿到此值.
执行过程:
二. 简单标签
SimpleTag接口:继承于JspTag接口
SimpleTagSupport类:实现于SimpleTag接口
方法:
setJspContext方法:将JSP页面的pageContext对象传递进来.由容器执行
setParent方法:把父标签处理器对象传递给当前标签处理器对象, 只有在标签存在父标签的情况下,WEB容器才会调用这个方法。由容器执行
getParent方法:获取当前标签的父标签处理器对象
doTag:用于处理所有的标签逻辑.当抛出SkipPageException异常,则是告诉WEB容器不再执行JSP页面位于结束标记后的内容.
JspFragment类:
方法:
getJspContext:得到JSP页面的PageContext对象
publicabstract void invoke(java.io.Writer out):用于执行JspFragment对象所代表的JSP代码片段. 参数out用于指定将JspFragment对象的执行结果写入到哪个输出流对象中,如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。
JspFragment.invoke()方法:
在标签处理器中如果没有调用JspFragment.invoke方法,其结果就相当于忽略标签体内容
在标签处理器中重复调用JspFragment.invoke方法,则标签体内容将会被重复执行
若想在标签处理器中修改标签体内容,只需在调用invoke方法时指定一个可取出结果数据的输出流对象(例如StringWriter),让标签体的执行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行修改后再输出到目标设备,即可达到修改标签体的目的。
三. JSTL核心标签库
c:out:输出指定内容,有默认值,可设置</>等符号是否转义
c:set:可设置类对象属性的值,也可以设置域对象属性的值
c:remove:删除指定域的指定属性
c:catch:可处理异常
c:if:判断
c:choose-c:when-c:otherwise:如if.else 这里注意:when可以有多个,而otherwise只能有一个
c:foreach:迭代
c:url:重写URL地址,如果带/,会带着应用名称.如果客户端cookie禁用,会带着sessionid
c:param:可放在url,redired中.会跟着url后的参数
c:redirect:请求重定向,其中context重定向另一个应用,不过无用.
c:forTokens:如 1923-3/02 13:22:00 设置-/: 结果1923 3 02 13 22 00
StringTokenizer:此类如同c:forTokens一样的功能