TIP:简单标签
简单标签定义的5个方法:
1、 setJspContext方法
用于把JSP页面的pageContext对象传递给标签处理器对象
2、 setParent方法
用于把父标签处理器对象传递给当前标签处理器对象
3、 getParent方法
用于获得当前标签的父标签处理器对象
4、 setJspBody方法
用于把代表标签体的JspFragment对象传递给标签处理器对象
5、 doTag方法
用于完成所有的标签逻辑,包括输出、迭代、修改标签体内容等。在doTag方法中可以抛出javax.servlet.jsp.SkipPageException异常,用于通知WEB容器不再执行JSP页面中位于结束标记后面的内容,这等效于在传统标签的doEndTag方法中返回Tag.SKIP_PAGE常量的情况。
TIP:Simple Tag接口方法的执行顺序:
1、 当web容器开始执行标签时,会调用如下方法完成标签的初始化
(1)WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象。
(2)WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法。
(3)如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。
(4)如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来。
2、 执行标签时:
容器调用标签处理器的doTag()方法,开发人员在方法体内通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的
Tip:JspFragment类
1、 javax.servlet.jsp.tagext.JspFragment类是在JSP2.0中定义的,它的实例对象代表JSP页面中的一段符合JSP语法规范的JSP片段,这段JSP片段中不能包含JSP脚本元素。
2、 WEB容器在处理简单标签的标签体时,会把标签体内容用一个JspFragment对象表示,并调用标签处理器对象的setJspBody方法把JspFragment对象传递给标签处理器对象。JspFragment类中只定义了两个方法,如下所示:
3、 getJspContext方法
a) 用于返回代表调用页面的JspContext对象.
4、publicabstract void invoke(java.io.Writer out)
• 用于执行JspFragment对象所代表的JSP代码片段
• 参数out用于指定将JspFragment对象的执行结果写入到哪个输出流对象中,如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。(简而言之,可以理解为写给浏览器)
TIP:invoke方法
利用这个方法可以控制是否执行和输出标签体的内容、是否迭代执行标签体的内容或对标签体的执行结果进行修改后再输出
在标签处理器中如果没有调用JspFragment.invoke方法,其结果就相当于忽略标签体内容;
在标签处理器中重复调用JspFragment.invoke方法,则标签体内容将会被重复执行;
若想在标签处理器中修改标签体内容,只需在调用invoke方法时指定一个可取出结果数据的输出流对象(例如StringWriter),让标签体的执行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行修改后再输出到目标设备,即可达到修改标签体的目的。
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
publicclass SimpleTagDemo extends SimpleTagSupport {
@Override
public void doTag() throws JspException,IOException {
// TODO Auto-generated method stub
//系统自动调用,把标签体中的内容封装成对象
JspFragmentjf=this.getJspBody();//得到标签体对象
jf.invoke(this.getJspContext().getOut());//输出到客户端
//jf.invoke(null);//输出到客户端
super.doTag();
}
}
scriptless无脚本的,不能再带有脚本
用简单标签控制迭代
1) 创建标签处理器
2) 在tld文件中进行描述
//把标签体中的内容显示10次
JspFragment jf=this.getJspBody();
for(int i=0;i<10;i++){
jf.invoke(null);
}
灵活的传参数,然后循环
在tld文件中要设置一些属性所必需的
<attribute>
<name>count</name>
<required>true</required>//设置属性是否是必须得
<rtexprvalue>true</rtexprvalue>//是否支持运行时表达式计算<csdn:demo8 count=”${date}”>或<csdn:demo8 count=”<%=5+8%>”>,可以写true可以写false,当写true时,也可以直接给count赋值
</attribute>
SimpleTagDemo8.java
private int count;
public void setCount(int count) {
this.count = count;
}
@Override
public void doTag() throws JspException, IOException {
JspFragment jf=this.getJspBody();
for(int i=0;i<count;i++){
jf.invoke(null);
}
TagDemo8.jsp
<csdn:demo8 count="5">
This is my JSP page. <br>
</csdn:demo8>
简单标签控制标签体的修改
JspFragment jf=this.getJspBody();//得到标签体
//存到缓冲区
//能获取缓冲区中的内容的流对象
StringWriter sw=new StringWriter();
jf.invoke(sw);//括号里的参数是流对象,通过流对象获取标签上的内容
String content=sw.toString().toUpperCase();//小写转换为大写
//得到输出流对象
JspWriter jw=this.getJspContext().getOut();
jw.write(content);
怎样开发带属性的标签:
<csdn:demo8 count=”${4+1}”></csdn>
标签处理器中一定也得包含一个私有的属性count和setter方法
doTag()包含业务逻辑代码
tld文件:
<tag>
<name>demo9</name>
<tag-class>com.hbsi.tag.SimpleTagDemo9</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>count</name>
<required>true|false</required>//设置属性是否是必须得
<rtexprvalue>true|false</rtexprvalue>
</attribute>
</tag>
防盗链:<dhw:referrer site=http://localhost/>
//提供了防盗链的网站,page如果一旦出现盗链情况,就跳到一个页面
RefererTag部份
import java.io.IOException;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
importjavax.servlet.jsp.SkipPageException;
importjavax.servlet.jsp.tagext.SimpleTagSupport;
public class RefererTag extends SimpleTagSupport {
private String site;
private String page;
@Override
public void doTag() throws JspException, IOException {
// TODO Auto-generatedmethod stub
//jc是pc的子类
JspContext jc=this.getJspContext();
PageContext pc=(PageContext)jc;
HttpServletRequest request=(HttpServletRequest)pc.getRequest();
String referer=request.getHeader("referer");//得到请求消息头
//利用重定向跳转到首页
//得到应答对象
HttpServletResponse response=(HttpServletResponse)pc.getResponse();
if(referer==null || !referer.startsWith(site)){
//盗链,跳转到首页上,当前页面后面的内容不处理,所有抛异常
//得到上下文对象再跳转到指定页面
if(page.startsWith(request.getContextPath())){
response.sendRedirect(page);
}else if(page.startsWith("/")){
response.sendRedirect(request.getContextPath()+page);
}else{
response.sendRedirect(request.getContextPath()+"/"+page);
}
throw new SkipPageException();
}
}
public void setSite(String site) {
this.site = site;
}
public void setPage(String page) {
this.page = page;
}
}
TestReferer.jsp部分
<%@taglib uri="http://www.dhw.com"prefix="dhw" %>
<dhw:referer site="http://localhost" page="/index.jsp"/>
<body>
明星信息————————明星信息
</body>
index.jsp部分:
<a href=”/20111108/example/TestReferer.jsp”>明星档案</a>
Dhw.tld部分:
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>dhw</short-name>
<uri>http://www.dhw.com</uri>
<tag>
<name>referer</name>
<tag-class>com.hbsi.tag.RefererTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>site</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>page</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>