【转载】Java Web学习(二十三) --- jsp自定义标签开发入门

匿名 (未验证) 提交于 2019-12-02 21:53:32

装载自:https://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、使用""指令引入要使用的标签库。

例如:在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>

  标签的运行效果如下:

  

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

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

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

  JSP引擎遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照JSP规范定义的通信规则依次调用它的方法。




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

  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 }

方法中的代码

  ①、这里是实例化一个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)

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

  这里以一个入门级的案例来讲解javaweb的自定义标签开发,在后面的博文中会进行更加详尽的介绍。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!