自定义标签

来源:互联网 发布:餐饮软件破解版 编辑:程序博客网 时间:2024/05/22 23:19

 提出问题 : 自定义标签可以降低 jsp 开发的复杂度和维护量.从 html 角度来说,可以使 html 不用去过多的关注那些比较复杂的商业逻辑.利用自定义标签,可以软件开发人员和页面设计人员合理分工:页面设计人员可以把精力集中在使用标签(HTML,XML或者JSP)创建网站上,而软件开发人员则可以将精力集中在实现底层功能上面,如国际化等,从而提高了工程生产力.将具有共用特性的tag库应用于不同的项目中,体现了软件复用的思想。

  什么是自定义标签 : 用户定义的一种自定义的jsp标记。当一个含有自定义标签的jsp页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为标签处理类的对象的操作。于是,当jsp页面被jsp引擎转化为servlet后,实际上tag标签被转化为了对tag处理类的操作.

   标签库 API:  标签库 API 定义在 javax.servlet.jsp.tagext 包中.

   传统标签和简单标签: 开发自定义标签,其核心就是要编写处理器类,一个标签对应一个标签处理器类,而一个标签库则是很多标签处理器的集合。所有的标签处理器类都要实现 JspTag 接口,该接口中没有定义任何方法,主要作为 Tag 和 SimpleTag 接口的父接口. 在 JSP 2.0 以前,所有标签处理器类都必须实现 Tag 接口,这样的标签称为传统标签. JSP 2.0 规范又定义了一种新的类型的标签,称为简单标签,其对应的处理器类要实现 SimpleTag 接口

   标签的形式:

      空标签:<hello/>
      带有属性的空标签:
       <max num1=“3” num2=“5”/>
      带有内容的标签:
       <greeting>
            hello
       </greeting>
      带有内容和属性的标签:
       <greeting name=“Tom”>
           hello
       </greeting>

自定义标签的开发与应用步骤:(这个很重要的哦!)

  1. 编写完成标签功能的 Java 类(标签处理器)
  2. 编写标签库描述(tld)文件,在tld文件中对自定义中进行描述
  3. 在 JSP 页面中导入和使用自定义标签

SimpleTag 接口:

  1. setJspContext 方法:该方法把代表 JSP 页面的 pageContext 对象传递给标签处理器对象。
  2. setParent 方法:该方法把父标签处理器对象传递给当前标签处理器对象
  3. getParent 方法:该方法用于获得标签的父标签处理器对象
  4. setJspBody 方法:该方法用于把代表标签体的 JspFragment 对象传递给标签处理器对象
  5. doTag 方法:该方法用于完成所有的标签逻辑。该方法可以抛出         javax.servlet.jsp.SkipPageException 异常,用于通知 web 容器不再执行 JSP 页面中位于结束标记后面的内容。

 

实现 SimpleTag 接口的标签处理器类的生命周期:

  1.Jsp 引擎将代表 JSP 页面的 pageContext 对象传递给标签处理器对象
  2.Jsp 引擎将父标签处理器对象传递给当前标签处理器对象。只有存在父标签 时,jsp 引擎才会调用该方法
  3.设置标签属性。只有定义属性才调用该方法
  4. 若存在标签体, JSP 引擎将把标签体封装成一个 JspFragment 对象,调用 setJspBody 方法将  JspFragment 对象传递给标签处理器对象。若标签体为空,这 setJspBody 将不会被 JSP 引擎调用
  5.容器调用标签处理器对象的 doTag 方法执 行标签逻辑

JspFragment 类:
    该类的实例对象代表 JSP 页面中的一段符合 JSP 语法规范的 JSP 片段,这段 JSP 片段不能包含 JSP 脚本元素(<% … %>).JSP 引擎在处理简单标签的标签体时,会把标签体内容用一个 JspFragment  对象表示,并调用标签处理器对象的 setJspBody 方法把 JspFragment 对象传递给标签处理器对象。得到代表标签体的 JspFragment 对象后,标签开发者和就可以在标签处理器中根据需要调用 JspFragment 对象的方法,进而决定如何处理标签体getJspContext 方法:该方法用于返回代表调用页面的 JspContext 对象
Invoke 方法(java.io.Writer out):该方法用于执行 JspFragment 对象所代表的 JSP 代码片段。在 doTag() 方法中可以根据需要调用该方法。该方法的参数 out 用于指定将 JspFragment 对象的执行结果写入到哪个输出流对象中。若传递参数 out 的值为 null,则将执行结果写入到  JspContext.geOut() 方法返回的输出流对象中。若想在标签处理器中修改标签体内容:需在调用 invoke 方法时指定一个可取出结果数据的输出流对象(如:StringWriter),让标签体的执行结果输出到该输出流中,然后从该输出流对象中取出数据进行修改后在输出到目标设备.

 SimpleTagSupport:
     为简化简单标签处理器的编写工作,JSP API 中提供了SimpleTag接口的一个实现SimpleTagSupport.
SimpleTagSupport实现了SimpleTag接口中的方法,它内部以成员变量的形式保存了setJspContext方法和setJspBody方法传递进来的参数。此外,它还定义了如下两个方法、来返回这两个参数:
    1.  getJspContext方法:该方法用于返回代表调用页面的JspContext对象
    2. getJspBody方法:该方法用于得到代表标签体的JspFragment对象

标签库描述文件:

    标签库描述(Tag Library Description)文件简称为 tld 文件,其扩展名为 .tld多个标签的集合就形成了一个标签库,标签库中的所有标签都必须在标签文件中进行描述Tld  文件可以放置在 web 应用程序的 WEB-INF 目录及其子目录中,但不能放置在 WEB-INF 目录下的 classes 和 lib 子目录中 。tld 文件也可以放置在 WEB-INF/lib 目录下的 jar 包的 META-INF 目录及其子目录中<body-content>:指定标签体的类型。可能取值有 3 种:
        empty:没有标签体 
        scriptless:标签体可以包含 el 表达式和 JSP 动作元素,但不能包含 JSP 的脚本元素
        tagdependent:表示标签体交由标签本身去解析处理。若指定 tagdependent,在标签体中的所有代码都会原封不动的交给标签处理器,而不是将执行结果传递给标签处理器

在 JSP 页面引用自定义标签:
    在 JSP 页面使用 taglib 指令引入标签库描述文件: <%@ taglib prefix=“” uri=“” %>.uri:属性用于指定所引入的标签库描述(tld)文件中所定义的 <uri> 元素的内容;prefix 属性用于为引入的 tld 文件指定一个”引用代号”。Prefix 属性可以由 jsp 文件的作者任意指定,只要与其他 taglib 指令的 prefix 属性值不同就可以。

   EL 自定义函数开发步骤:

  1. 编写 EL 自定义函数映射的Java 类中的静态方法: 这个 Java 类必须带有 public 修饰符,方法必须是这个类的带有 public 修饰符的静态方法
  2. 编写标签库描述文件(tld 文件), 在 tld 文件中描述自定义函数
  3. 在 JSP 页面中导入和使用自定义函数

在 tld 文件中描述 EL 自定义函数:

在 JSP 页面中导入和使用 EL 自定义函数,在标准 JSP 页面中使用 taglib 指令来引入 tld 文件:
<%@ taglib uri="/petrelskyTag" prefix="petrelsky"%>uri:属性用于指定所引入的标签库描述(tld)文件中所定义的 <uri> 元素的内容;prefix 属性用于为引入的 tld 文件指定一个”引用代号”。Prefix 属性可以由 jsp 文件的作者任意指定,只要与其他 taglib 指令的 prefix 属性值不同就可以。调用 EL 自定义函数:     ${petrelsky :toGBK (param.username) } 

 

    根据上面的理论知识的讲解,现在我将举写例子,并写写我的心得:

第一步,写JAVA类标签处理器

package cn.itcast.simpleTag;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;

public class ParamTag implements SimpleTag {
 
 private PageContext pageContext = null;

 public void doTag() throws JspException, IOException {
  System.out.println("hello doTag....");
  HttpServletRequest request = null;
  JspWriter out = null;
  request = (HttpServletRequest) pageContext.getRequest();
  out = pageContext.getOut();
  String name = request.getParameter("name");
  out.print("Hello: " + name);
 }

 public JspTag getParent() {
  return null;
 }

 public void setJspBody(JspFragment arg0) {
 }

 public void setJspContext(JspContext arg0) {
  this.pageContext = (PageContext) arg0;
 }

 public void setParent(JspTag arg0) {
 }
}

第2步写TLD 文件

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">
   
  <description>myTag 1.1 core library</description>
  <display-name>myTag core</display-name>
  <tlib-version>1.0</tlib-version>
  <short-name>itcast</short-name>
 
  <uri>http://itcast.cn/jsp/mytag</uri>
 
  <tag>
    <name>param</name>
    <tag-class>cn.itcast.simpleTag.ParamTag</tag-class>
    <body-content>empty</body-content>
  </tag>
</taglib>

 

第三步写JSP 页面 :

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/WEB-INF/tld/mytag_1_ex.tld" prefix="itcast" %>

<html>
  <head><title>My JSP 'test.jsp' starting page</title></head>
  <body>
    <itcast:param/>
  </body>
</html>

由上面可以看出,所谓标签就是用在视图层,JSP页面中根本看不到JAVA 的程序,而是JAVA 程序写了个标签,然后在JSP 页面中使用,页面看起来十分简洁!这个就是自定义标签的强大之处!前提是以JAVA为基础的!看着佟老师在课上写自定义标签是那么的熟练,当时就想自己也能够有这样水平,当然思路很重要,但最重要的是自己经常性学着自己去写的!下面再看个复杂点的!

 

package cn.itcast.simpleTag.ex;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;

public class ToLowerCaseTag implements SimpleTag {
 
 private PageContext pageContext;
 private JspFragment bodyContent;

 public void doTag() throws JspException, IOException {
  // TODO Auto-generated method stub
  //1. 得到标签体的文本
  StringWriter sw = new StringWriter();
  
  bodyContent.invoke(sw);
  String bodyContentString = sw.toString();
  
  //2. 把标签体文本变成小写
  bodyContentString = bodyContentString.toLowerCase();
  
  //3. 输出
  pageContext.getOut().print(bodyContentString);
 }

 public JspTag getParent() {
  // TODO Auto-generated method stub
  return null;
 }

 public void setJspBody(JspFragment arg0) {
  // TODO Auto-generated method stub
  this.bodyContent = arg0;
 }

 public void setJspContext(JspContext arg0) {
  // TODO Auto-generated method stub
  this.pageContext = (PageContext) arg0;
 }

 public void setParent(JspTag arg0) {
  // TODO Auto-generated method stub

 }

}

 

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">
   
  <description>mytag</description>
  <display-name>mytag core</display-name>
  <tlib-version>1.2</tlib-version>
  <short-name>itcast</short-name>
  <uri>http://itcast.cn/mytag_ex</uri>
 
  <tag>
   <name>toLowerCase</name>
   <tag-class>cn.itcast.simpleTag.ToLowerCaseTag</tag-class>
   <body-content>scriptless</body-content>
  </tag>
 
</taglib>

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/WEB-INF/tld/mytag.tld" prefix="itcast" %>

<html>
  <head><title>My JSP 'test.jsp' starting page</title></head>
  <body>
    <itcast:toLowerCase>
     HELLO ITCAST.CN.
    </itcast:toLowerCase>
  </body>
</html>

    这个例子很明显的证明了开发自定义标签的步骤是多么的重要的!只要自己勤加练习,其实我们也可以写出很漂亮的,很有使用价值的标签供给大家使用的呢!