说下开发的环境
1,eclipse for java EE;
2, tomcat 7.0.42
3, windows 7
首先,新建一个动态web工程。
然后在javaResource目录下,新建一个类,这个类就是用来完成你的标签的功能的。
通常情况下,这个类需要实现Tag接口。
上面这些方法各自完成自己的功能。sun公司已经为了我们定义了一个实现该接口的类,通常我们只需要继承这个已经实现
Tag接口的TagSupport类就可以。
但对于开始学些标签,最好还是自己实现Tag接口较好,这样能够让自己更加清楚程序的运行原理。
我们先去找到TagSupport的源代码:
这里面方法还是很多的,不过对于开始只实现一个简单功能来说,先不要管这些,我们只需找到那些在Tag接口里存在的方法。
看看这个类是如何实现那些方法的。并对这些方法进行简单的分析。
public int doStartTag() throws JspException {
return SKIP_BODY;
}
这个方法是非常重要的,它的意思就是标签开始执行,会做一些什么。比如我们一会要实现的功能,就是全部在这个方法
里完成。
对于该类来说,这个方法里就一条语句,return SKIP_BODY;究竟什么意思,我也不懂,但是这个SKIP_BODY被设置为了0.(见TAG标签的定义)
但是很明显,这里没有任何的输出。
/*
public final static int SKIP_BODY = 0;
public final static int EVAL_BODY_INCLUDE = 1;
public final static int SKIP_PAGE = 5;
public final static int EVAL_PAGE = 6;
*/
public int doEndTag() throws JspException {
return EVAL_PAGE;
}
这个方法是执行到结束标签该做一些什么。return 6?也不大明白。但是在制作第一个标签的时候,我们不需要明白
这个返回是什么意思,甚至都不要理会这个方法。一会只需要照着抄就行了,而且我们可以试着返回下其他值。
或者在这里做一些输出操作,看看会发生什么事情。
public void setPageContext(PageContext pageContext) {
this.pageContext = pageContext;
}
这个方法,应该属于一个关键一点的方法了。因为这里涉及到一个变量pageContext,所以,我们需要在自己定义的
类中申明这个变量。这个返回值就是当前使用该标签的pageContext,通过这个pageContext,我们可以获取很多
JPS页面的信息,pageContext可以获取其他所有的page域,以及....
public void setParent(Tag t) {
parent = t;
}
这个先不要理会,没有什么作用。通常会在 if else这种标签的外面,套上一个父标签。
public Tag getParent() {
return parent;
}
同上。
public void release() {
parent = null;
id = null;
if( values != null ) {
values.clear();
}
values = null;
}
这个就是释放资源,看这里,就是将里面的变量设置为空,而这里有一个value,我们开始应该并不需要什么value,
所以就别管了。
好了。明白了这些信息。
我们就可以自己制作自己的标签了,我们实现的功能就是调用一个标签的时候,就会打印出来访者的Ip地址。
<mytag:ShowIp/>
在JSP页面就会显示IP地址。
类已经写完。
那么接下来,我们就需要设定一条通道,让这个类的功能,能够到JSP页面里实现。
我们一共需要以下几步来完成。
1,将这个类配置成一条路径,并且使用一个简单的标签名来标志这个类。这个我们通常在一个xml文件里完成。
在WEB-INF目录下新建一个文件,SimpleTag.tld(当然,名字随便你取)
这个XML文件里主要注意的是以下两个区域:
1,
<tag>
<name>ShowIp</name>
<tag-class>cn.dzr.web.tag.ShowIP</tag-class>
<body-content>empty</body-content>
<description>显示IP地址</description>
</tag>
将标签的类,用ShowIP这个名字代表。注意类名必须是完成的类名,也就是包括其所在的包名。
名字的话,从语法上来说,你可以随便取,但是最好取一个和其功能相对应的名字。
接着下面的
<body-content>empty</body-content>
表示是否需要使用开始标签和结束标签之间的内容。我们这里当然不需要,所以设置为了空。
下面的<description>显示IP地址</description>为描述信息。
你可以写,或者不写。
这里注意一点,name ->tag-class body-context description 可以不写,但是如果写,就必须按照这个顺序。
相信学过XML的都知道,有一个shcema或者DTD规定了严格的顺序。
2,
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>simple</short-name>
<uri>http://www.dzrtag.com</uri>
这四行,第一行,第二行,是版本号。我也不大清楚不同版本有何不同。但是就是复制过来即可。
重要的是uri,这个uri就是通道的核心。他起到连接JSP和tag类的作用。
你这里设定一个值。具体的形式不清楚,但是我这里就是采用这种网站全名的格式。不纠结这个问题。
设定之后,我们就可以在JSP页面里使用这个标签了。
JSP页面内容如下
需要注意的有两个地方。
1,
<%@taglib uri="http://www.dzrtag.com" prefix="mytag" %>
这一句,看到这个uri没,机会是刚刚我上面写的uri,正是它,让JSP和TAG类关联了起来。
而这个后面的prefix 则是一个名称,语法你可以随便取名(除了一些sun公司不让你取的)
2,
<mytag:ShowIp/>
这里,就是使用刚刚你自己定义的标签了。
,你打开这个JSP,就会显示IP地址了。当你使用localhost:8080.。。。。访问的时候,他会显示一串000.
你用127.0.0.1访问的时候,则会显示127.0.0.1
系统可能出现一条错误信息:
resolved in either web.xml or the jar files deployed with this application。
我在网上找了半天的原因,最后通过重启tomcat解决了问题。或许是因为那个tld文件在配置之后,需要重启Tomcat才能
生效吧。
如果遇到一些无法解决的错误,重启也是一个不错的解决办法的。
最后,我对doEndTag方法进行了修改。
发现在页面上的IP地址后面,会显示 如果这是一个错误,那么该如何处理。
1,eclipse for java EE;
2, tomcat 7.0.42
3, windows 7
首先,新建一个动态web工程。
然后在javaResource目录下,新建一个类,这个类就是用来完成你的标签的功能的。
通常情况下,这个类需要实现Tag接口。
(Tag接口的内容如下:)
public interface Tag extends JspTag {
public final static int SKIP_BODY = 0;
public final static int EVAL_BODY_INCLUDE = 1;
public final static int SKIP_PAGE = 5;
public final static int EVAL_PAGE = 6;
void setPageContext(PageContext pc);
void setParent(Tag t);
Tag getParent();
int doStartTag() throws JspException;
int doEndTag() throws JspException;
void release();
}
上面这些方法各自完成自己的功能。sun公司已经为了我们定义了一个实现该接口的类,通常我们只需要继承这个已经实现
Tag接口的TagSupport类就可以。
但对于开始学些标签,最好还是自己实现Tag接口较好,这样能够让自己更加清楚程序的运行原理。
我们先去找到TagSupport的源代码:
package javax.servlet.jsp.tagext;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
public class TagSupport implements IterationTag, Serializable {
public static final Tag findAncestorWithClass(Tag from, Class klass) {
boolean isInterface = false;
if (from == null ||
klass == null ||
(!Tag.class.isAssignableFrom(klass) &&
!(isInterface = klass.isInterface()))) {
return null;
}
for (;;) {
Tag tag = from.getParent();
if (tag == null) {
return null;
}
if ((isInterface && klass.isInstance(tag)) ||
klass.isAssignableFrom(tag.getClass()))
return tag;
else
from = tag;
}
}
public TagSupport() { }
public int doStartTag() throws JspException {
return SKIP_BODY;
}
public int doEndTag() throws JspException {
return EVAL_PAGE;
}
public int doAfterBody() throws JspException {
return SKIP_BODY;
}
public void release() {
parent = null;
id = null;
if( values != null ) {
values.clear();
}
values = null;
}
public void setParent(Tag t) {
parent = t;
}
public Tag getParent() {
return parent;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setPageContext(PageContext pageContext) {
this.pageContext = pageContext;
}
public void setValue(String k, Object o) {
if (values == null) {
values = new Hashtable<String, Object>();
}
values.put(k, o);
}
public Object getValue(String k) {
if (values == null) {
return null;
} else {
return values.get(k);
}
}
public void removeValue(String k) {
if (values != null) {
values.remove(k);
}
}
public Enumeration<String> getValues() {
if (values == null) {
return null;
}
return values.keys();
}
// private fields
private Tag parent;
private Hashtable<String, Object> values;
protected String id;
protected PageContext pageContext;
}
这里面方法还是很多的,不过对于开始只实现一个简单功能来说,先不要管这些,我们只需找到那些在Tag接口里存在的方法。
看看这个类是如何实现那些方法的。并对这些方法进行简单的分析。
public int doStartTag() throws JspException {
return SKIP_BODY;
}
这个方法是非常重要的,它的意思就是标签开始执行,会做一些什么。比如我们一会要实现的功能,就是全部在这个方法
里完成。
对于该类来说,这个方法里就一条语句,return SKIP_BODY;究竟什么意思,我也不懂,但是这个SKIP_BODY被设置为了0.(见TAG标签的定义)
但是很明显,这里没有任何的输出。
/*
public final static int SKIP_BODY = 0;
public final static int EVAL_BODY_INCLUDE = 1;
public final static int SKIP_PAGE = 5;
public final static int EVAL_PAGE = 6;
*/
public int doEndTag() throws JspException {
return EVAL_PAGE;
}
这个方法是执行到结束标签该做一些什么。return 6?也不大明白。但是在制作第一个标签的时候,我们不需要明白
这个返回是什么意思,甚至都不要理会这个方法。一会只需要照着抄就行了,而且我们可以试着返回下其他值。
或者在这里做一些输出操作,看看会发生什么事情。
public void setPageContext(PageContext pageContext) {
this.pageContext = pageContext;
}
这个方法,应该属于一个关键一点的方法了。因为这里涉及到一个变量pageContext,所以,我们需要在自己定义的
类中申明这个变量。这个返回值就是当前使用该标签的pageContext,通过这个pageContext,我们可以获取很多
JPS页面的信息,pageContext可以获取其他所有的page域,以及....
public void setParent(Tag t) {
parent = t;
}
这个先不要理会,没有什么作用。通常会在 if else这种标签的外面,套上一个父标签。
public Tag getParent() {
return parent;
}
同上。
public void release() {
parent = null;
id = null;
if( values != null ) {
values.clear();
}
values = null;
}
这个就是释放资源,看这里,就是将里面的变量设置为空,而这里有一个value,我们开始应该并不需要什么value,
所以就别管了。
好了。明白了这些信息。
我们就可以自己制作自己的标签了,我们实现的功能就是调用一个标签的时候,就会打印出来访者的Ip地址。
<mytag:ShowIp/>
在JSP页面就会显示IP地址。
package cn.dzr.web.tag;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;
public class ShowIP implements Tag
{
Tag parent;
PageContext pageContext;
public void setPageContext(PageContext pc)
{
//将pageContext传递给这个类,这是我们实现下面操作的前提。
//在接下来,我们肯定需要使用pageContext的功能的。
this.pageContext = pc;
}
public void setParent(Tag t)
{
this.parent = t;
}
public Tag getParent()
{
return this.parent;
}
@Override
public int doStartTag() throws JspException
{
//显示IP
HttpServletRequest request = (HttpServletRequest)this.pageContext.getRequest();
JspWriter out = this.pageContext.getOut();
String ip = request.getRemoteAddr();
try
{
out.write(ip);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
return 0;
}
public int doEndTag() throws JspException
{
return 0;
}
public void release()
{
//释放资源
this.parent = null;
this.pageContext = null;
}
}
类已经写完。
那么接下来,我们就需要设定一条通道,让这个类的功能,能够到JSP页面里实现。
我们一共需要以下几步来完成。
1,将这个类配置成一条路径,并且使用一个简单的标签名来标志这个类。这个我们通常在一个xml文件里完成。
在WEB-INF目录下新建一个文件,SimpleTag.tld(当然,名字随便你取)
其内容如下:
<!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>simple</short-name>
<uri>http://www.dzrtag.com</uri>
<tag>
<name>ShowIp</name>
<tag-class>cn.dzr.web.tag.ShowIP</tag-class>
<body-content>empty</body-content>
<description>显示IP地址</description>
</tag>
</taglib>
这个XML文件里主要注意的是以下两个区域:
1,
<tag>
<name>ShowIp</name>
<tag-class>cn.dzr.web.tag.ShowIP</tag-class>
<body-content>empty</body-content>
<description>显示IP地址</description>
</tag>
将标签的类,用ShowIP这个名字代表。注意类名必须是完成的类名,也就是包括其所在的包名。
名字的话,从语法上来说,你可以随便取,但是最好取一个和其功能相对应的名字。
接着下面的
<body-content>empty</body-content>
表示是否需要使用开始标签和结束标签之间的内容。我们这里当然不需要,所以设置为了空。
下面的<description>显示IP地址</description>为描述信息。
你可以写,或者不写。
这里注意一点,name ->tag-class body-context description 可以不写,但是如果写,就必须按照这个顺序。
相信学过XML的都知道,有一个shcema或者DTD规定了严格的顺序。
2,
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>simple</short-name>
<uri>http://www.dzrtag.com</uri>
这四行,第一行,第二行,是版本号。我也不大清楚不同版本有何不同。但是就是复制过来即可。
重要的是uri,这个uri就是通道的核心。他起到连接JSP和tag类的作用。
你这里设定一个值。具体的形式不清楚,但是我这里就是采用这种网站全名的格式。不纠结这个问题。
设定之后,我们就可以在JSP页面里使用这个标签了。
JSP页面内容如下
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://www.dzrtag.com" prefix="mytag" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>自定义标签的使用</title>
</head>
<body>
<mytag:ShowIp/>
</body>
</html>
需要注意的有两个地方。
1,
<%@taglib uri="http://www.dzrtag.com" prefix="mytag" %>
这一句,看到这个uri没,机会是刚刚我上面写的uri,正是它,让JSP和TAG类关联了起来。
而这个后面的prefix 则是一个名称,语法你可以随便取名(除了一些sun公司不让你取的)
2,
<mytag:ShowIp/>
这里,就是使用刚刚你自己定义的标签了。
,你打开这个JSP,就会显示IP地址了。当你使用localhost:8080.。。。。访问的时候,他会显示一串000.
你用127.0.0.1访问的时候,则会显示127.0.0.1
系统可能出现一条错误信息:
resolved in either web.xml or the jar files deployed with this application。
我在网上找了半天的原因,最后通过重启tomcat解决了问题。或许是因为那个tld文件在配置之后,需要重启Tomcat才能
生效吧。
如果遇到一些无法解决的错误,重启也是一个不错的解决办法的。
最后,我对doEndTag方法进行了修改。
public int doEndTag() throws JspException
{
JspWriter out = this.pageContext.getOut();
String str = "如果这是一个错误,那么该如何处理。";
try
{
out.write(str);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
return 0;
}
发现在页面上的IP地址后面,会显示 如果这是一个错误,那么该如何处理。