首页 > 代码库 > jsp tag

jsp tag

jsp标签涉及的类层次结构如图:

技术分享

jsp标签定义步骤:

1)创建标签处理类

public class MyTag extends TagSupport{
//
}

2)tld文件定义

3)引入标签

<%@ taglib prefix="my" uri="/my-tags" %>
<my:mytag date="yyyy-MM-dd HH-mm-ss" first=" {这是我第一个属性}">

jsp tag原理分析

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 = http://www.mamicode.com/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 = http://www.mamicode.com/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; }
}

 

jsp tag