自定义标签为了避免jsp中出现java代码,以至于view层混乱,所以自定义标签使View层更简洁。
1.写一个继承了TagSupport类的java类,如下
public class ViewIPTag extends TagSupport {
@Override
public int doStartTag() throws JspException {
HttpServletRequest request=(HttpServletRequest) this.pageContext.getRequest();
JspWriter out=this.pageContext.getOut();
try {
out.println(request.getRemoteAddr());
} catch (IOException e) {
throw new RuntimeException(e);
}
return super.doStartTag();
}
}
2.在WEB-INF目录下写tld文件,记得写uri,使其绑定到某个链接上,当jsp关联这个链接,就相当于使用了tld同链接的tag,如下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>debug</short-name>
<uri>http://www.wanhao.com</uri>
<tag>
<name>viewIP</name>
<tag-class>com.wanhao.ViewIPTag</tag-class>
<body-content>TAGDEPENDENT</body-content>
</tag>
</taglib>
3.写jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.wanhao.com" prefix="wan"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP '2.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
您的ip是:<wan:viewIP/>
</body>
</html>
自定义标签还可以
1.控制是否显示标签内文本:
当实现TagSupport的类返回 EVAL_BODY_INCLUDE 时,显示标签内的文本内容。
当其返回 SKIP_BODY 时,不显示标签内文本内容。
2.控制这个jsp的剩余页面是否显示,只需要重写doEndTag()方法
@Override
public int doEndTag() throws JspException {
// TODO Auto-generated method stub
return SKIP_PAGE;
}
3.重复标签内容
主要重写两个方法,若是doAfterBody()方法返回 EVAL_BODY_AGAIN ,则重新执行标签
static int i=5;
@Override
public int doAfterBody() throws JspException {
i--;
if(i>0)
return EVAL_BODY_AGAIN;
else
return SKIP_BODY;
}
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
return EVAL_BODY_INCLUDE;
}
4.修改标签内容
需要继承BodyTagSupport类,实现doStartTag()返回EVAL_BODY_BUFFERED时,把BodyContent内容传给doEndTag()
public class Demo4 extends BodyTagSupport {
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
return EVAL_BODY_BUFFERED;
}
@Override
public int doEndTag() throws JspException {
BodyContent bc= getBodyContent();
String con=bc.getString();
try {
pageContext.getOut().println(con.toUpperCase());
} catch (IOException e) {
e.printStackTrace();
}
return EVAL_PAGE;
}
}
上面的内容在做项目中不太常见,因为还有更加简便的方法,之所以介绍上述方法,是为了便于以后读懂框架代码。
接下来就介绍更简便的方法。
写一个实现了 SimpleTagSupport 的类,其它的和上述相同,只需要这一个类便可以实现所有功能。
1.控制标签体内容的显示与隐藏
取消注释表示没有将 JspFragment 中的内容加入输出流对象的缓冲区,不会显示,反之显示
public class SimpleTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
JspFragment jf=this.getJspBody();
//jf.invoke(this.getJspContext().getOut());
}
}
2.控制标签内容重复展示
也可以写 jf.invoke(null); 这不是将 JspFragment 的对象内容注入空流对象 ,而是默认对 JspContext() 对应输出流对象注入信息。
public class SimpleTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
JspFragment jf=this.getJspBody();
for(int i=0;i<5;++i)
jf.invoke(this.getJspContext().getOut());
}
}
3.跳过jsp页面的剩余部分
@Override
public void doTag() throws JspException, IOException {
throw new SkipPageException();
}
4.修改标签内容
先把输出信息传给StringWiter流对象(其父类Writer),获取字符串并改变后,将结果加到真正在页面显示的流对象的缓冲区。
public class SimpleTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
JspFragment jf = this.getJspBody();
StringWriter sw=new StringWriter();
jf.invoke(sw);
String content=sw.toString().toUpperCase();
this.getJspContext().getOut().write(content);
}
}
简单标签的高级用法:
给标签加上属性值
1.在对应的实现类加上一个属性,并声明其get set方法。
2.在调用此标签的实先tld文件的标签中,加入这一属性,并建议设置
<required>true</required>
<rtexprvalue>true</rtexprvalue> 控制是否标签属性可以是表达式,如${} <%= %>等
例如:
public class SimpleTag extends SimpleTagSupport {
private Date today;
public Date getToday() {
return today;
}
public void setToday(Date today) {
this.today = today;
}
@Override
public void doTag() throws JspException, IOException {
JspFragment jf = this.getJspBody();
StringWriter sw=new StringWriter();
sw.write(today.toLocaleString());
jf.invoke(sw);
String content=sw.toString().toUpperCase();
this.getJspContext().getOut().write(content);
}
}
<tag>
<name>SimpleDemo4</name>
<tag-class>com.wanhao.SimpleTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>today</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>