`
jianfulove
  • 浏览: 120000 次
  • 性别: Icon_minigender_1
  • 来自: 湛江
社区版块
存档分类
最新评论

JSP标签在tomcat中的运行原理

    博客分类:
  • JSP
阅读更多


        在网上找了很多关于jsp标签的文章,但大多数都是只是告诉你怎么去使用,怎么去编写一个jsp标签。几乎没有可以从源头上告诉你怎么去理解原理,它在tomcat中又是怎么样的呢?所以我花一点时间整理一编关于jsp标签原理的文章,如有什么不周祥之处还望各位大侠谅解。
     
        首先我们需要大致了解开发自定义标签所涉及到的接口与类的层次结构(其中SimpleTag接口与SimpleTagSupport类是JSP2.0中新引入的)。

  

         (一) JSP自定义标签的定义步骤:

            1  创建标记处理类

            2   创建TLD文件

            3   在jsp页面通

                过指令引入标签库

    

 

 

 

 

1、处理标签的类必须扩展javax.servlet.jsp.TagSupport 或 BodyTagSupport。先来讨论TagSupport

2、TagSupport类的主要属性:

A.parent属性:代表嵌套了当前标签的上层标签的处理类;

B.pageContex属性:代表Web应用中的javax.servlet.jsp.PageContext对象;

3、JSP容器在调用doStartTag或者doEndTag方法前,会先调用setPageContext和setParent方法,设置pageContext和parent。因此在标签处理类中可以直接访问pageContext变量;

4、在TagSupport的构造方法中不能访问pageContext成员变量,因为此时JSP容器还没有调用setPageContext方法对pageContext进行初始化。

 

先写一个扩展javax.servlet.jsp.TagSupport的标签类MyTag :

package com.common.tag;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

public class MyTag extends TagSupport
{
    int i=1;
    String first;
    String date;
    JspWriter jw;
public int doStartTag() throws JspException {
    jw=super.pageContext.getOut();
    try {
        jw.print("this is first field :"+getFirst() +"<br/>");
        jw.print("this is first date :"+getDate() +"<br/>");
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    return TagSupport.EVAL_BODY_INCLUDE;
}
 
  public int doAfterBody() throws JspException {
      try {
        jw.println(i++ + "     :我想知道这里doafterbody都做了些什么了呢<br/>");
        
    } catch (IOException e) {
        e.printStackTrace();
    }
      if(5==i)return TagSupport.SKIP_BODY;
     return TagSupport.EVAL_BODY_AGAIN;
    }
  
  public int doEndTag() throws JspException {
      try {
        jw.print("最后的结束标签了,doendtag");
    } catch (IOException e) {
        e.printStackTrace();
    }
      return TagSupport.EVAL_PAGE;
    }
  public String getFirst() {
        return first;
    }
    public void setFirst(String first) {
        this.first = first;
    }
    public String getDate() {
        SimpleDateFormat sdf=new SimpleDateFormat(date);
        return sdf.format(new Date());
    }
    public void setDate(String date) {
        this.date = date;
    }
  
}
 

 

 

 我们以Tomcat 6.0.20服务器为例,来看看最简单的myTag.jsp是怎么运行的。

    我们仅以myTag.jsp中的 <my:mytag/>标签的解析为例进行分析,看容器是怎样把这个自定义标签解析成HTML输出的。

<%@ taglib prefix="my" uri="/my-tags" %>
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
  </head>
  
  <body>
       <br>
    
    <my:mytag date="yyyy-MM-dd HH-mm-ss" first=" {这是我第一个属性}">
    
      中间体执行吧。
    
    </my:mytag>
    
  </body>
</html>

 

   先附上我执行的结果:

 

this is first field : {这是我第一个属性}
this is first date :2013-03-10 01-28-02
中间体执行吧。 1 :我想知道这里doafterbody都做了些什么了呢
中间体执行吧。 2 :我想知道这里doafterbody都做了些什么了呢
中间体执行吧。 3 :我想知道这里doafterbody都做了些什么了呢
中间体执行吧。 4 :我想知道这里doafterbody都做了些什么了呢
最后的结束标签了,doendtag

 

    让我们来看看Tomcat都做了什么。转到Tomcat的\work\Standalone\localhost\_目录下,可以找到如下的myTag_jsp.java,这个文件就是Tomcat解析myTag.jsp时生成的源文件:

 

public final class myTag_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  static {
    _jspx_dependants = new java.util.ArrayList(1);
    _jspx_dependants.add("/WEB-INF/myTag.tld");
  }

   //为所有的定制标签定义处理器池类的引用 
  private org.apache.jasper.runtime.TagHandlerPool _005fjspx_005ftagPool_005fmy_005fmytag_0026_005ffirst_005fdate;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;
..................
.............
//为处理器池类赋值
 public void _jspInit() {
    _005fjspx_005ftagPool_005fmy_005fmytag_0026_005ffirst_005fdate = org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(getServletConfig());
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }
  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                  null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("\r\n");

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
        ................
     .......................
      out.write("  <body>\r\n");
      out.write("    This is my JSP page. <br>\r\n");
      out.write("    \r\n");
      out.write("    ");
      if (_jspx_meth_my_005fmytag_005f0(_jspx_page_context)) //标签的处理,请往下看方法的实现。
        return;
      out.write("\r\n");
      out.write("    \r\n");
      out.write("    \r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
                 //真正处理标签<my:myTag  >方法
  private boolean _jspx_meth_my_005fmytag_005f0(PageContext _jspx_page_context)
          throws Throwable {
    PageContext pageContext = _jspx_page_context;
    JspWriter out = _jspx_page_context.getOut();
    //  my:mytag
    com.common.tag.MyTag _jspx_th_my_005fmytag_005f0 = (com.common.tag.MyTag) _005fjspx_005ftagPool_005fmy_005fmytag_0026_005ffirst_005fdate.get(com.common.tag.MyTag.class);
//JSP容器在调用doStartTag或者doEndTag方法前,会先调用setPageContext和setParent方法,设置pageContext和parent,而且也调用setFiled()方法设置标签的相关属性;
    _jspx_th_my_005fmytag_005f0.setPageContext(_jspx_page_context);
    _jspx_th_my_005fmytag_005f0.setParent(null);
    // /index.jsp(19,4) name = date type = java.lang.String reqTime = false required = false fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null
    _jspx_th_my_005fmytag_005f0.setDate("yyyy-MM-dd HH-mm-ss");
    // /index.jsp(19,4) name = first type = java.lang.String reqTime = false required = false fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null
    _jspx_th_my_005fmytag_005f0.setFirst(" {这是我第一个属性}");
    int _jspx_eval_my_005fmytag_005f0 = _jspx_th_my_005fmytag_005f0.doStartTag();   // JSP容器 处理                                                                                 //到自 定义标签的起始标志,就会调用doStartTag()方法
    if (_jspx_eval_my_005fmytag_005f0 != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {  //如果doStartTag()方
                                                                                               // 法返回值不是Tag.SKIP_BODY就执行标签体
      do {
        out.write("\r\n");
        out.write("    \r\n");
        out.write("      中间体执行吧。\r\n");         
        out.write("    \r\n");
        out.write("    ");
        int evalDoAfterBody = _jspx_th_my_005fmytag_005f0.doAfterBody();              //看到这里你应该知道
                                                                                                      //tomcat是怎么处理doAfterBody(); 了吧。
        if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN) //如果doAfterBody()返
                                                      //回值是EVAL_BODY_AGAIN,则再次执行方法体和doAfterBody()方法,
                                                                                                                                 // 直到doAfterBody()返
                                                                                                                     //回值为SKIP_BODY才跳出循环
          break;
      } while (true);
    }               //do{}while(true)无论doAfterBody()返回值如何都会执行方法体一次
    if (_jspx_th_my_005fmytag_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {
      _005fjspx_005ftagPool_005fmy_005fmytag_0026_005ffirst_005fdate.reuse(_jspx_th_my_005fmytag_005f0);
      return true;
    }
    _005fjspx_005ftagPool_005fmy_005fmytag_0026_005ffirst_005fdate.reuse(_jspx_th_my_005fmytag_005f0);
    return false;
  }
}

 

   生成的myTag_jsp.java继承于org.apache. jasper.runtime.HttpJspBase。研究这个文件为我们了解定制标签的运行机理提供了途径。

   从上面可以看出,Tomcat在解析一个JSP页面时,首先为每一个定制标签定义并实例化了一个TagHandlerPool对象。页面的处理方法覆盖 父类的_ jspService()方法,_jspService方法首先初始化环境,为内置对象赋值。由于myTag.jsp页面整体由一 个<html:html/>标签包裹,Tomcat对每一个标签都产生一个私有方法加以实现。<html:html/>标签的处 理方法是_jspx_meth_html_html_0()。这个方法的命名规范大家也可以从这里看出,就是“_jspx_meth + 标签的前缀 + 标签名 + 该标签在JSP页面同类标签中出现的序号”。其它标签都被包含在该标签中,所以其它标签在_jspx_meth_html_html_0()方法中进行解 析。

  在_jspx_meth_html_html_0()方法中,首先从_jspx_tagPool_html_html_locale池中得到一个 org.apache.struts.taglib.html.HtmlTag的实例,然后设置这个tag实例的页面上下文及上级标签,由于 html:html标签是页面的最顶层标签,所以它的parent是null。然后对该标签的内容进行解析。HTML代码直接输出,下面主要看 看<html:html></html:html>标签之间包含的<my:mybodyTag count="5" >标签的解析。

                对<my:mytag>标签的解析类似于html:html,Tomcat也将其放入一个 单独的方法_jspx_meth_my_005fmytag_005f0()中进行。

在myTag.jsp中定义了一个<my:mytag>标签,并设置了一个属性: <my:mytag date="yyyy-MM-dd HH-mm-ss" first=" {这是我第一个属性}">。Tomcat在解析时,调用MyTag对象的date和first属性设置方法setDate()和setFirst(),将该属性置 入。然后调用MyTag的doStartTag()和doEndTag()方法,完成解析。如果doEndTag()方法的返回值为 javax.servlet.jsp.tagext.Tag. SKIP_PAGE,表明已经完成解析,返回true,Tomcat将立即停止剩余页面代码的执行,并返回。如果doEndTag()方法的返回值为TagSupport.EVAL_PAGE ,表明还没完成解析,返回false,继续解析这个标签后面的内容。并在最后把该MyTag的实例放回池 中。

  标签类对象实例的池化
  为了提高运行效率,Tomcat对所有的定制标签类进行了池化,池化工作由org.apache.jasper. runtime.TagHandlerPool类完成。TagHandlerPool类主要有两个方法,代码如下:

TagHandlerPool.java

public class TagHandlerPool {
private static final int MAX_POOL_SIZE = 5;
private Tag[] handlers;
public synchronized Tag get(Class handlerClass) throws JspException {……}
public synchronized void reuse(Tag handler) {……}
}
   TagHandlerPool简单地实现了对标签类的池化,其中MAX_POOL_SIZE是池的初始大小,handlers是一个Tag的数组,存储标 签类的实例。get(Class handlerClass)得到一个指定标签类的实例,如果池中没有可用实例,则新实例化一个。reuse(Tag handler)把handler对象放回池中。

  至此,我们对JSP在容器中的运行过程已经了然于胸 了。虽然每种JSP容器的解析结果会有差异,但其中的原理都雷同。对于编写JSP应用,我们并不需要干涉容器中的运行过程,但如果你对整个底层的运行机制 比较熟悉,就能对JSP/Servlet技术有更深的认识。

 

  

     二   我们再来讨论标签类继承BodyTagSupport

我们仅以myBodyTag.jsp中的 <my:mybody/>标签的解析为例进行分析,看容器是怎样把这个自定义标签解析成HTML输出的。

<%@ taglib prefix="my" uri="/my-tags" %>
            <html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
  </head>
  
  <body>
    <br/>    
    <my:mybodyTag count="5" >
    
                              中间体执行吧。<br/>
    
    </my:mybodyTag>
  </body>
</html>
 

 

先附上执行后的结果:

---dostartTag---
---setBodyContent---
---doinitBody---

0 :---doAfterBody---

1 :---doAfterBody---

2 :---doAfterBody---

3 :---doAfterBody---

4 :---doAfterBody---

---doEndTag---
中间体执行吧。
中间体执行吧。
中间体执行吧。
中间体执行吧。
中间体执行吧。
中间体执行

 

          让我们来看看Tomcat都做了什么。转到Tomcat的\work\Standalone\localhost\_目录下,可以找到如下的myBodyTag_jsp.java,这个文件就是Tomcat解析myBodyTag.jsp时生成的源文件:

 

public final class myBodyTag_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  static {
    _jspx_dependants = new java.util.ArrayList(1);
    _jspx_dependants.add("/WEB-INF/myTag.tld"); //加载标签描述文件
  }
           //为所有的定制标签定义处理器池类的引用 
  private org.apache.jasper.runtime.TagHandlerPool _005fjspx_005ftagPool_005fmy_005fmybodyTag_0026_005fcount;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _005fjspx_005ftagPool_005fmy_005fmybodyTag_0026_005fcount = org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(getServletConfig());//给处理池类赋值
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }

  public void _jspDestroy() {
    _005fjspx_005ftagPool_005fmy_005fmybodyTag_0026_005fcount.release();
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html; charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                  null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("\r\n");

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

      out.write("\r\n");
      out.write("\r\n");
      out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("<html>\r\n");
      out.write("  <head>\r\n");
      out.write("    <base href=\"");
      out.print(basePath);
      out.write("\">\r\n");
      out.write("    \r\n");
      out.write("    <title>My JSP 'index.jsp' starting page</title>\r\n");
      out.write("  </head>\r\n");
      out.write("  \r\n");
      out.write("  <body>\r\n");
      out.write("    <br/>    \r\n");
      out.write("    ");
      if (_jspx_meth_my_005fmybodyTag_005f0(_jspx_page_context))
        return;             //标签被处理的方法
      out.write("\r\n");
      out.write("    \r\n");
      out.write("    \r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }

  private boolean _jspx_meth_my_005fmybodyTag_005f0(PageContext _jspx_page_context)
          throws Throwable {
    PageContext pageContext = _jspx_page_context;
    JspWriter out = _jspx_page_context.getOut();
    //  my:mybodyTag
    com.common.tag.MyBodyTag _jspx_th_my_005fmybodyTag_005f0 = (com.common.tag.MyBodyTag) _005fjspx_005ftagPool_005fmy_005fmybodyTag_0026_005fcount.get(com.common.tag.MyBodyTag.class);
    _jspx_th_my_005fmybodyTag_005f0.setPageContext(_jspx_page_context);
    _jspx_th_my_005fmybodyTag_005f0.setParent(null);
    // /myBodyTag.jsp(18,4) name = count type = java.lang.String reqTime = false required = false fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null
    _jspx_th_my_005fmybodyTag_005f0.setCount(5);
    int _jspx_eval_my_005fmybodyTag_005f0 = _jspx_th_my_005fmybodyTag_005f0.doStartTag();          //执行.doStartTag()
    if (_jspx_eval_my_005fmybodyTag_005f0 != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {                           //继承BodyTagSupport处继承TagSupport不同之处就是以下标为棕色的代码了。
      if (_jspx_eval_my_005fmybodyTag_005f0 != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {    
        out = _jspx_page_context.pushBody();   //如果dostartTag()返回BodyTagSupport.EVAL_BODY_BUFFERED; 注意了此时的out 引用已经被改赋值为BodyContent对象了。它会把它会通过out.print()设置标签体的内容缓存起来,
直到super.bodyContent.writeOut(getPreviousOut())执行到再输出标签体的内容
                                                                    
        _jspx_th_my_005fmybodyTag_005f0.setBodyContent((javax.servlet.jsp.tagext.BodyContent) out); //setBodyContent()方法用于设置标签体内容,如果在此之前要作一些初始化工作,
                                                                                                                                                                     //则在doInitBody()方法中完成
        _jspx_th_my_005fmybodyTag_005f0.doInitBody();
      }
      do {
        out.write("\r\n");
        out.write("    \r\n");
        out.write("                              中间体执行吧。<br/>\r\n");
        out.write("    \r\n");
        out.write("    ");
        int evalDoAfterBody = _jspx_th_my_005fmybodyTag_005f0.doAfterBody();           //这里在讲继承TagSupport处理类时是一样的,请看前面
        if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)
          break;
      } while (true);
      if (_jspx_eval_my_005fmybodyTag_005f0 != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {
        out = _jspx_page_context.popBody();
      }
    }
    if (_jspx_th_my_005fmybodyTag_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {  //这里执行了.doEndTag()方法//如果 此方法中没有super.bodyContent.writeOut(getPreviousOut());这一句时,
                                                                                                                                                               //则标签体内容没有输出!
      _005fjspx_005ftagPool_005fmy_005fmybodyTag_0026_005fcount.reuse(_jspx_th_my_005fmybodyTag_005f0);
      return true;
    }
    _005fjspx_005ftagPool_005fmy_005fmybodyTag_0026_005fcount.reuse(_jspx_th_my_005fmybodyTag_005f0);
    return false;
  }
}

 

 最后总结一下BodyTagSupport执行流程:

他们执行顺序如下:
doStartTag()—>doInitBody()-->setBodyContent()-->doAfterBody()-->doEndTag() 


doStartTag()方法可返回EVAL_BODY_INCLUDE或SKIP_BODY,还有EVAL_BODY_BUFFERED;
如果返回EVAL_BODY_INCLUDE则继续执行; 如果返回EVAL_BODY_BUFFERED; 注意了此时的out 引用已经被改赋值为BodyContent对象了。它会把它会通过out.print()设置标签体的内容缓存起来,

直到super.bodyContent.writeOut(getPreviousOut())执行到再输出标签体的内容
如果返回SKIP_BODY则接下来的setBodyContent(), doInitBody(),doAfterBody()三个方法不会被执行,
而直接执行doEndTag()方法。
setBodyContent()方法用于设置标签体内容,如果在此之前要作一些初始化工作,则在doInitBody()方法中完成。
标签体内容执行完后,会调用doAfterBody()方法,此方法可返回EVAL_BODY_TAG, SKIP_BODY,
EVAL_PAGE或SKIP_PAGE。
如果返回EVAL_BODY_TAG则会再次设置标签体内容,直到返回SKIP_BODY;
如果返回EVAL_PAGE则标签体执行完后会继续执行JSP页面中接下来的部分;
如果返回SKIP_PAGE,则JSP页面的后续内容将不再执行。

 

        附上MyBodyTag类:

          

 package com.common.tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class MyBodyTag extends BodyTagSupport
{
    int count;
    int iteraterCount;

    JspWriter jw;
    BodyContent bc;
  
    public int doStartTag() throws JspException {
        try {
            jw=super.pageContext.getOut();
            jw.print("---dostartTag---<br/>");
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return BodyTagSupport.EVAL_BODY_BUFFERED;
    }
    
    public void doInitBody() throws JspException {
        try {
            jw.print("---doinitBody---<br/><br/>");
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
    public void setBodyContent(BodyContent b) {
        try {
            jw.print("---setBodyContent---<br/>");
        } catch (IOException e) {
            e.printStackTrace();
        }
        super.setBodyContent(b);
   }
    public int doAfterBody() throws JspException {
      if(iteraterCount<count){
          try {
            jw.print(iteraterCount++ +" :---doAfterBody---<br/><br/>");
        } catch (IOException e) {
            e.printStackTrace();
        }
        
          
          return BodyTagSupport.EVAL_BODY_AGAIN;
      }else {
        return BodyTagSupport.SKIP_BODY;
    }
    
    }
    public int doEndTag() throws JspException {//如果 此方法没有,则标签体内容没有输出!
        try {
        jw.print("---doEndTag---<br/>");
    if(super.bodyContent!=null){
                super.bodyContent.writeOut(getPreviousOut());
        }
    
        } catch (IOException e) {
            e.printStackTrace();
        }
        iteraterCount=0;
        return BodyTagSupport.EVAL_PAGE;
    }


    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

 

          附上myTag.TLD:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
  <description><![CDATA["To make it easier to access dynamic data;
                        the Apache Struts framework includes a library of custom tags.
                        The tags interact with the framework's validation and internationalization features;
                        to ensure that input is correct and output is localized.
                        The Struts Tags can be used with JSP FreeMarker or Velocity."]]></description>
  <display-name>"my Tags"</display-name>
  <tlib-version>1.0</tlib-version>
  <short-name>mytag</short-name>
  <uri>/my-tags</uri>
  
  <tag>
    <description><![CDATA[Execute an action from within a view]]></description>
    <name>mytag</name>
    <tag-class>com.common.tag.MyTag</tag-class>
    <body-content>JSP</body-content>
    <attribute>
      <description><![CDATA[Whether the result of this action (probably a view) should be executed/rendered]]></description>
      <name>first</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[Whether the writer should be flush upon end of action component tag, default to true]]></description>
      <name>date</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
</tag>


<tag>
<name>mybodyTag</name>
<tag-class>com.common.tag.MyBodyTag</tag-class>
<body-content>JSP</body-content>

 <attribute>
      <name>count</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
</tag>
</taglib>
     
 

 

 

5
3
分享到:
评论
7 楼 sunrainstone 2013-03-11  
6 楼 shikui 2013-03-11  
终于可以说话了,这个必须得顶!富哥,牛!!!
5 楼 freezingsky 2013-03-11  
文章太长了,没有仔细看。但个人觉得,jsp标签,本身 就是用java代码来编写的,其实和servlet应该一样的,都会在tomcat下编译好,然后在页面中进行替换。
4 楼 宋建勇 2013-03-11  
宋建勇 写道
nice

手势反了,sorry
3 楼 宋建勇 2013-03-11  
nice
2 楼 jianfulove 2013-03-10  
laogao3232 写道
那么复杂,tag标签不是java代码写的?其实就行java代码吧,转成html代码。

     呵呵,tomcat中处理jsp标签原理是这样了,也不是很复杂吧。
1 楼 laogao3232 2013-03-10  
那么复杂,tag标签不是java代码写的?其实就行java代码吧,转成html代码。

相关推荐

    jsp自定义标签例子,能在Tomcat下直接运行

    在JSP自定义标签的例子中,我们可以看到这个压缩包文件可能包含了一个完整的示例项目,可以在Apache Tomcat这样的Servlet容器下直接运行。Apache Tomcat是一款开源的Servlet容器,广泛用于部署和运行Java Web应用...

    精选JSP可运行模板(可在tomcat上运行)

    以下是在Tomcat上部署和运行JSP模板的步骤: 1. **下载和安装Tomcat**: 首先,你需要从Apache官网下载并安装Tomcat服务器。 2. **配置环境变量**: 设置JAVA_HOME指向你的JDK安装路径,CATALINA_HOME指向Tomcat的...

    IIS与JSP整合TOMCAT

    在标签中提到的"IIS JSP TOMCAT 环境整合 isapi_redirect",这强调了整合涉及的关键技术点。环境整合通常包括以下步骤: 1. 安装和配置Tomcat服务器,确保其正常运行。 2. 下载并安装ISAPI Redirector,将其添加到...

    jsp运行原理

    ### JSP运行原理详解 #### 一、JSP的基本概念 JSP(Java Server Pages)是一种结合了HTML标记和Java代码的技术,用于创建动态网页。它允许开发人员将业务逻辑和展示逻辑分离,使得Web应用更加模块化和易于维护。 ...

    jsp+tomcat的wap源码

    【标题】"jsp+tomcat的wap源码" 涉及的知识点主要集中在使用Java Server Pages (JSP) 技术与Apache Tomcat服务器来开发...学习者可以通过分析和运行这个项目,深入理解JSP与Tomcat在实际应用中的工作原理和交互方式。

    jsp+tomcat开发的小论坛

    在【标签】"jsp+tomcat开发的小论坛"中,我们可以推断出项目的重点在于JSP和Tomcat的整合应用。这包括但不限于如何配置Tomcat服务器以运行JSP页面,如何使用JSP动作元素(如&lt;jsp:include&gt;,&lt;jsp:forward&gt;等)和脚本...

    jsp(Tomcat)中errorPage不能使用的原因解决方法,Jsp技术文章,JSP系列教程,Jsp.htm.rar

    在Java服务器页面(JSP)开发中,Tomcat是一个广泛使用的应用服务器,它为运行JSP文件提供了必要的环境。在JSP中,`errorPage`元素是用于处理应用程序中的异常和错误的重要机制。然而,有时可能会遇到`errorPage`...

    jsp+留言板+tomcat

    【标题】:“jsp+留言板+tomcat”是一个基于Java服务器页面(JSP)技术构建的简单留言板应用,它在Tomcat服务器环境下运行。这个项目对于初学者和有经验的Web开发者来说,都是一个很好的实践案例,可以深入理解JSP、...

    tomcat6.0安装版及Jsp测试方法.rar

    标题中的“tomcat6.0安装版及Jsp测试方法”表明了这个压缩包内容是关于Tomcat 6.0的安装教程以及如何在Tomcat环境下测试JSP页面的指导。Tomcat是一款广泛使用的开源Java Servlet容器,尤其适用于运行JSP和Servlet...

    以Tomcat服务器为核心的3种配置JSP环境.,tomcat的配置

    5. **运行与调试**:直接在IDE中启动Tomcat,运行或调试你的JSP应用。 方法三:使用Maven或Gradle构建工具 1. **创建项目**:使用Maven或Gradle创建一个Java Web项目,添加相应的依赖,如`tomcat7-maven-plugin`或...

    Eclipse调用Tomcat服务的原理

    2. **编写并运行页面**:在“Hello”项目中创建一个简单的JSP页面,如`index.jsp`,并在其中添加文本内容:“HelloEclipseandTomcat6.0”。接着通过Eclipse的菜单选项“Run as”-&gt;“Run on Server”启动项目。 3. *...

    JSP环境配置(用Tomcat做服务器)

    同时,添加`CATALINA_HOME`环境变量指向Tomcat的安装目录,并在`Path`变量中加入 `%CATALINA_HOME%\bin`,以便于通过命令行启动Tomcat。 ### 二、启动Tomcat服务器 1. **启动Tomcat**:在`%CATALINA_HOME%\bin`...

    JDK,JSP,TOMCAT图解环境安装配置

    四、JSP在Tomcat中的部署与运行 1. 创建Web应用:一个基本的Web应用包含WEB-INF目录,其中放置web.xml配置文件,以及WEB-INF外的静态资源(HTML、CSS、JS)和JSP文件。 2. 部署应用:将Web应用的根目录复制到Tomcat...

    tomcat8.5 jsp servlet WebSocket等api文档

    在Java Web开发中,Tomcat 8.5、JSP、Servlet和WebSocket是四个至关重要的技术组件。这些API文档提供了开发者在构建动态Web应用程序时所需的详细指南和参考资料。 首先,让我们详细了解一下每个技术: 1. **Tomcat...

    Tomcat 源代码调试 - 看不见的 Shell 第二式之隐藏任意 Jsp 文件1

    在深入探讨Tomcat源代码调试和“看不见的Shell第二式之隐藏任意Jsp文件”的概念之前,我们需要了解一些基础的JSP和Tomcat工作原理。 JSP(JavaServer Pages)是一种动态网页技术,允许开发者在HTML中嵌入Java代码,...

    OA系统源码,采用jsp前台,tomcat服务器

    在本源码中,JSP主要负责用户界面的展示,通过JSP标签库和脚本元素与后端JavaBean交互,获取或提交数据。 2. **Servlet**: 虽然在描述中没有直接提到Servlet,但JSP通常与Servlet配合工作。Servlet是Java Web应用...

    jsp+tomcat网上购物系统完整版

    而Tomcat是Apache软件基金会的Jakarta项目中的一个核心项目,是一个开源的、轻量级的Web应用服务器,常用于运行JSP和Servlet。 【描述】中提到“完整版”意味着这个系统包含了所有必要的组成部分,包括源代码和...

    JSP Tomcat7 提示JSTL错误.zip_JSP Tomcat7 提示JSTL错误

    这些标签需要对应的JAR文件支持才能在JSP页面中正常运行。在本问题中,两个关键的JAR文件是`jstl-1.2.jar`和`standard-1.1.2.jar`。`jstl-1.2.jar`包含了JSTL的主要实现,而`standard-1.1.2.jar`则包含了EL...

Global site tag (gtag.js) - Google Analytics