javaweb学习总结(二十三)——jsp自定义标签开发入门

转自:http://www.cnblogs.com/xdp-gacl/p/3916734.html

一、自定义标签的作用

  自定义标签主要用于移除Jsp页面中的java代码。

二、自定义标签开发和使用

2.1、自定义标签开发步骤

   1、编写一个实现Tag接口的Java类(标签处理器类)

 1 package me.gacl.web.tag;
 2
 3 import java.io.IOException;  4  5 import javax.servlet.http.HttpServletRequest;  6 import javax.servlet.jsp.JspException;  7 import javax.servlet.jsp.JspWriter;  8 import javax.servlet.jsp.PageContext;  9 import javax.servlet.jsp.tagext.Tag; 10 11 public class ViewIPTag implements Tag { 12 13 //接收传递进来的PageContext对象 14 private PageContext pageContext; 15 16  @Override 17 public int doEndTag() throws JspException { 18 System.out.println("调用doEndTag()方法"); 19 return 0; 20  } 21 22  @Override 23 public int doStartTag() throws JspException { 24 System.out.println("调用doStartTag()方法"); 25 HttpServletRequest request =(HttpServletRequest) pageContext.getRequest(); 26 JspWriter out = pageContext.getOut(); 27 String ip = request.getRemoteAddr(); 28 try { 29 //这里输出的时候会抛出IOException异常 30  out.write(ip); 31 } catch (IOException e) { 32 //捕获IOException异常后继续抛出 33 throw new RuntimeException(e); 34  } 35 return 0; 36  } 37 38  @Override 39 public Tag getParent() { 40 return null; 41  } 42 43  @Override 44 public void release() { 45 System.out.println("调用release()方法"); 46  } 47 48  @Override 49 public void setPageContext(PageContext pageContext) { 50 System.out.println("setPageContext(PageContext pageContext)"); 51 this.pageContext = pageContext; 52  } 53 54  @Override 55 public void setParent(Tag arg0) { 56 57  } 58 59 }

  2、在WEB-INF/目录下新建tld文件,在tld文件中对标签处理器类进行描述

  

  gacl.tld文件的代码如下:

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2
 3 <taglib xmlns="http://java.sun.com/xml/ns/j2ee"  4  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  5  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"  6  version="2.0">  7 <!-- description用来添加对taglib(标签库)的描述 -->  8 <description>孤傲苍狼开发的自定义标签库</description>  9 <!--taglib(标签库)的版本号 --> 10 <tlib-version>1.0</tlib-version> 11 <short-name>GaclTagLibrary</short-name> 12 <!-- 13  为自定义标签库设置一个uri,uri以/开头,/后面的内容随便写,如这里的/gacl , 14  在Jsp页面中引用标签库时,需要通过uri找到标签库 15  在Jsp页面中就要这样引入标签库:<%@taglib uri="/gacl" prefix="gacl"%> 16 --> 17 <uri>/gacl</uri> 18 19 <!--一个taglib(标签库)中包含多个自定义标签,每一个自定义标签使用一个tag标记来描述 --> 20 <!-- 一个tag标记对应一个自定义标签 --> 21 <tag> 22 <description>这个标签的作用是用来输出客户端的IP地址</description> 23 <!-- 24  为标签处理器类配一个标签名,在Jsp页面中使用标签时是通过标签名来找到要调用的标签处理器类的 25  通过viewIP就能找到对应的me.gacl.web.tag.ViewIPTag类 26 --> 27 <name>viewIP</name> 28 <!-- 标签对应的处理器类--> 29 <tag-class>me.gacl.web.tag.ViewIPTag</tag-class> 30 <body-content>empty</body-content> 31 </tag> 32 33 </taglib>

2.2、在Jsp页面中使用自定义标签

  1、使用"<%@taglib uri="标签库的uri"  prefix="标签的使用前缀"%>"指令引入要使用的标签库。

例如:在jspTag_Test1.jsp中引用gacl标签库

 1 <%@ page language="java" pageEncoding="UTF-8"%>  2 <!-- 使用taglib指令引用gacl标签库,标签库的前缀(prefix)可以随便设置,如这里设置成 prefix="xdp" -->  3 <%@taglib uri="/gacl" prefix="xdp"%>  4 <!DOCTYPE HTML>  5 <html>  6 <head>  7 <title>输出客户端的IP</title>  8 </head>  9 10 <body> 11  你的IP地址是(使用java代码获取输出): 12 <% 13 //在jsp页面中使用java代码获取客户端IP地址 14 String ip = request.getRemoteAddr(); 15  out.write(ip); 16 %> 17 <hr/> 18  你的IP地址是(使用自定义标签获取输出): 19 <%--使用自定义标签viewIP --%> 20 <xdp:viewIP/> 21 </body> 22 </html>

  标签的运行效果如下:

  

  从运行效果种可以看到,使用自定义标签就可以将jsp页面上的java代码移除掉,如需要在jsp页面上输出客户端的IP地址时,使用 <xdp:viewIP/>标签就可以代替jsp页面上的这些代码:

1 <%
2         //在jsp页面中使用java代码获取客户端IP地址
3 String ip = request.getRemoteAddr(); 4  out.write(ip); 5 %>

  这就是开发和使用自定义标签的好处,可以让我们的Jsp页面上不嵌套java代码。

三、自定义标签的执行流程

  JSP引擎遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照JSP规范定义的通信规则依次调用它的方法。
    1、public void setPageContext(PageContext pc), JSP引擎实例化标签处理器后,将调用setPageContext方法将JSP页面的pageContext对象传递给标签处理器,标签处理器以后可以通过这个pageContext对象与JSP页面进行通信。
    2、public void setParent(Tag t),setPageContext方法执行完后,WEB容器接着调用的setParent方法将当前标签的父标签传递给当前标签处理器,如果当前标签没有父标签,则传递给setParent方法的参数值为null。
    3、public int doStartTag(),调用了setPageContext方法和setParent方法之后,WEB容器执行到自定义标签的开始标记时,就会调用标签处理器的doStartTag方法。
    4、public int doEndTag(),WEB容器执行完自定义标签的标签体后,就会接着去执行自定义标签的结束标记,此时,WEB容器会去调用标签处理器的doEndTag方法。
    5、public void release(),通常WEB容器执行完自定义标签后,标签处理器会驻留在内存中,为其它请求服务器,直至停止web应用时,web容器才会调用release方法。

  我们在tomcat服务器的"work\Catalina\localhost\JavaWeb_JspTag_study_20140816\org\apache\jsp"目录下可以找到将jspTag_Test1.jsp翻译成Servlet后的java源代码,如下图所示:

  打开jspTag_005fTest1_jsp.java文件,可以看到setPageContext(PageContext pc)、setParent(Tag t)、doStartTag()、doEndTag()、release()这5个方法的调用顺序和过程。

  jspTag_005fTest1_jsp.java的代码如下:

  1 package org.apache.jsp;
  2
  3 import javax.servlet.*;  4 import javax.servlet.http.*;  5 import javax.servlet.jsp.*;  6  7 public final class jspTag_005fTest1_jsp extends org.apache.jasper.runtime.HttpJspBase  8 implements org.apache.jasper.runtime.JspSourceDependent {  9  10 private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();  11  12 private static java.util.List _jspx_dependants;  13  14 static {  15 _jspx_dependants = new java.util.ArrayList(1);  16 _jspx_dependants.add("/WEB-INF/gacl.tld");  17  }  18  19 private org.apache.jasper.runtime.TagHandlerPool _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody;  20  21 private javax.el.ExpressionFactory _el_expressionfactory;  22 private org.apache.AnnotationProcessor _jsp_annotationprocessor;  23  24 public Object getDependants() {  25 return _jspx_dependants;  26  }  27  28 public void _jspInit() {  29 _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody = org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(getServletConfig());  30 _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();  31 _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());  32  }  33  34 public void _jspDestroy() {  35  _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody.release();  36  }  37  38 public void _jspService(HttpServletRequest request, HttpServletResponse response)  39 throws java.io.IOException, ServletException {  40  41 PageContext pageContext = null;  42 HttpSession session = null;  43 ServletContext application = null;  44 ServletConfig config = null;  45 JspWriter out = null;  46 Object page = this;  47 JspWriter _jspx_out = null;  48 PageContext _jspx_page_context = null;  49  50  51 try {  52 response.setContentType("text/html;charset=UTF-8");  53 pageContext = _jspxFactory.getPageContext(this, request, response,  54 null, true, 8192, true);  55 _jspx_page_context = pageContext;  56 application = pageContext.getServletContext();  57 config = pageContext.getServletConfig();  58 session = pageContext.getSession();  59 out = pageContext.getOut();  60 _jspx_out = out;  61  62 out.write("\r\n");  63 out.write("<!-- 引用gacl标签库,标签库的前缀(prefix)可以随便设置,如这里设置成 prefix=\"gacl\" -->\r\n");  64 out.write("\r\n");  65 out.write("<!DOCTYPE HTML>\r\n");  66 out.write("<html>\r\n");  67 out.write(" <head>\r\n");  68 out.write(" <title>输出客户端的IP</title>\r\n");  69 out.write(" </head>\r\n");  70 out.write(" \r\n");  71 out.write(" <body>\r\n");  72 out.write(" 你的IP地址是(使用java代码获取输出):\r\n");  73 out.write(" ");  74  75 //在jsp页面中使用java代码获取客户端IP地址  76 String ip = request.getRemoteAddr();  77  out.write(ip);  78  79 out.write("\r\n");  80 out.write(" <hr/>\r\n");  81 out.write(" 你的IP地址是(使用自定义标签获取输出):");  82 if (_jspx_meth_xdp_005fviewIP_005f0(_jspx_page_context))  83 return;  84 out.write("\r\n");  85 out.write(" </body>\r\n"); 86 out.write("</html>\r\n"); 87 } catch (Throwable t) { 88 if (!(t instanceof SkipPageException)){ 89 out = _jspx_out; 90 if (out != null && out.getBufferSize() != 0) 91 try { out.clearBuffer(); } catch (java.io.IOException e) {} 92 if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); 93 } 94 } finally { 95 _jspxFactory.releasePageContext(_jspx_page_context); 96 } 97 } 98 99 private boolean _jspx_meth_xdp_005fviewIP_005f0(PageContext _jspx_page_context) 100 throws Throwable { 101 PageContext pageContext = _jspx_page_context; 102 JspWriter out = _jspx_page_context.getOut(); 103 // xdp:viewIP 104 me.gacl.web.tag.ViewIPTag _jspx_th_xdp_005fviewIP_005f0 = (me.gacl.web.tag.ViewIPTag) _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody.get(me.gacl.web.tag.ViewIPTag.class); 105 _jspx_th_xdp_005fviewIP_005f0.setPageContext(_jspx_page_context); 106 _jspx_th_xdp_005fviewIP_005f0.setParent(null); 107 int _jspx_eval_xdp_005fviewIP_005f0 = _jspx_th_xdp_005fviewIP_005f0.doStartTag(); 108 if (_jspx_th_xdp_005fviewIP_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) { 109 _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody.reuse(_jspx_th_xdp_005fviewIP_005f0); 110 return true; 111 } 112 _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody.reuse(_jspx_th_xdp_005fviewIP_005f0); 113 return false; 114 } 115 }

  下面重点分析一下上述代码中标红色的那个 private boolean _jspx_meth_xdp_005fviewIP_005f0(PageContext _jspx_page_context)方法中的代码

  ①、这里是实例化一个viewIP标签处理器类me.gacl.web.tag.ViewIPTag的对象

1  //  xdp:viewIP
2     me.gacl.web.tag.ViewIPTag _jspx_th_xdp_005fviewIP_005f0 = (me.gacl.web.tag.ViewIPTag) _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody.get(me.gacl.web.tag.ViewIPTag.class);

  ②、实例化标签处理器后,调用setPageContext方法将JSP页面的pageContext对象传递给标签处理器

1 _jspx_th_xdp_005fviewIP_005f0.setPageContext(_jspx_page_context);

  ③、setPageContext方法执行完后,接着调用的setParent方法将当前标签的父标签传递给当前标签处理器,如果当前标签没有父标签,则传递给setParent方法的参数值为null

1 _jspx_th_xdp_005fviewIP_005f0.setParent(null);

  ④、调用了setPageContext方法和setParent方法之后,WEB容器执行到自定义标签的开始标记时,就会调用标签处理器的doStartTag方法

1 int _jspx_eval_xdp_005fviewIP_005f0 = _jspx_th_xdp_005fviewIP_005f0.doStartTag();

  ⑤、WEB容器执行完自定义标签的标签体后,就会接着去执行自定义标签的结束标记,此时,WEB容器会去调用标签处理器的doEndTag方法

1 if (_jspx_th_xdp_005fviewIP_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE)

  这就是自定义标签的执行流程。

转载于:https://www.cnblogs.com/lyl-cnblogs/p/7743123.html

转载:javaweb学习总结(二十三)——jsp自定义标签开发入门相关推荐

  1. javaweb学习总结(二十三)——jsp自定义标签开发入门

    一.自定义标签的作用 自定义标签主要用于移除Jsp页面中的java代码. 二.自定义标签开发和使用 2.1.自定义标签开发步骤 1.编写一个实现Tag接口的Java类(标签处理器类) 1 packag ...

  2. javaweb学习总结(二十三):jsp自定义标签开发入门

    一.自定义标签的作用 自定义标签主要用于移除Jsp页面中的java代码. 二.自定义标签开发和使用 2.1.自定义标签开发步骤 1.编写一个实现Tag接口的Java类(标签处理器类) 1 packag ...

  3. JSP自定义标签开发入门

    一般情况下开发jsp自定义标签需要引用以下两个包 import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; 首先我们需要大致了解开发 ...

  4. javaweb学习总结(二十八)——JSTL标签库之核心标签

    一.JSTL标签库介绍 JSTL标签库的使用是为弥补html标签的不足,规范自定义标签的使用而诞生的.使用JSLT标签的目的就是不希望在jsp页面中出现java逻辑代码 二.JSTL标签库的分类 核心 ...

  5. JSP自定义标签开发与打包

    前言:最近用到JSP的自定义标签,于是到网上寻找资料,结果发现很多的网上教程要么不全要么就是步骤流程错误,尤其是将自定义标签打jar包这一过程,按照网上的教程操作,结果被坑惨了,所以才有现在这一篇博文 ...

  6. JSP自定义标签开发(五)——标签类获取 request 、 session

    标签类中要是能够取到 request 和 session 这样的对象,对于一个web开发员来说,那是一件多么幸福的事情啊!懂得了这个知识,标签开发与servlet结合的开发将变得随心所欲. 实例: p ...

  7. javaweb学习总结二十三(servlet开发之线程安全问题)

    一:servlet线程安全问题发生的条件 如果多个客户端访问同一个servlet时,发生线程安全问题,那么它们访问的是相同的资源.如果访问 的不是相同资源,则不存在线程安全问题. 实例1:不会产生线程 ...

  8. JavaWeb学习总结(二)——JSP中的九个内置对象

    一.JSP运行原理 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet ...

  9. JavaWeb学习总结(十七):JSP中的九个内置对象

    一.JSP运行原理 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet ...

最新文章

  1. 无向图的最小生成树(克鲁斯卡尔算法 Kruskal)
  2. HTML5 如何实现拖放'N'拖放
  3. POJ 2728 Desert King [最优比率生成树]
  4. 肺部ct重建_肺部CT血管分割及三维重建
  5. Hibernate【XXXX.hbm.xml】总结
  6. Functional Options
  7. 【三分+枚举】LNOI2017 d1t1 期末考试
  8. 基于matlab的人脸五官边缘检测方法,基于MATLAB的人脸识别系统的设计
  9. SpringBoot快速集成Apollo配置中心
  10. 一、“用黑色的眼睛寻找光明”
  11. python解初中题_用python解一道数独小题
  12. 网站 HTTP 升级 HTTPS 完全配置手册
  13. 数据分析:销售数据怎么分析?简单概述
  14. LFS-初入门第一篇(准备环境)
  15. 【干货】ubuntu18.04+win7双系统+双硬盘安装总结
  16. html div旋转45度,CSS动画 - 在每次悬停时进一步旋转45度
  17. Canal监听阿里云RDS
  18. RGB颜色与颜色名称对照表
  19. 以合力加速基础软件创新:拆解鲲鹏众智如何繁荣新计算生态
  20. 心과 情의 調和 (韓長庚 易學原理總論)

热门文章

  1. org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter错误解决
  2. 【分布式】Zookeeper请求处理
  3. 网络协议——TCP/IP协议
  4. 人活系列Streetlights (秩)
  5. 如何编写常见语言带默认参数值的函数
  6. Yii 框架里数据库操作详解-[增加、查询、更新、删除的方法](转)
  7. Android 基础教程之-------Android ProgressBar的使用!
  8. [ 搞笑 ] 疯狂的石头与张柏芝
  9. how to identify keywords for search on Google Scholar?
  10. what are the associated papers accepted at the Harvard business review from cambridge