JPS自定义标签初体验。

来源:互联网 发布:akgy50淘宝哪家是真货 编辑:程序博客网 时间:2024/06/05 08:26
说下开发的环境
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;    elsefrom = 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;}@Overridepublic int doStartTag() throws JspException{//显示IPHttpServletRequest 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地址后面,会显示 如果这是一个错误,那么该如何处理。

原创粉丝点击