详细讲解JSP自定义标签

详细讲解JSP自定义标签,第1张

   一 基本概念        标签(Tag)        标签是一种XML元素 通过标签可以使JSP网页变得简洁并且易于维护 还可以方便地实现同一个JSP文件支持多种语言版本 由于标签是XML元素 所以它的名称和属性都是大小写敏感的         标签库(Tag library)        由一系列功能相似 逻辑上互相联系的标签构成的集合称为标签库         标签库描述文件(Tag Library Descriptor)        标签库描述文件是一个XML文件 这个文件提供了标签库中类和JSP中对标签引用的映射关系 它是一个配置文件 和web xml是类似的         标签处理类(Tag Handle Class)        标签处理类是一个Java类 这个类继承了TagSupport或者扩展了SimpleTag接口 通过这个类可以实现自定义JSP标签的具体功能         二 自定义JSP标签的格式        为了使到JSP容器能够使用标签库中的自定义行为 必须满足以下两个条件         )从一个指定的标签库中识别出代表这种自定义行为的标签         )找到实现这些自定义行为的具体类         第一个必需条件 找出一个自定义行为属于那个标签库 是由标签指令的前缀(Taglib Directive s Prefix)属性完成 所以在同一个页面中使用相同前缀的元素都属于这个标签库 每个标签库都定义了一个默认的前缀 用在标签库的文档中或者页面中插入自定义标签 所以 你可以使用除了诸如jsp jspx java servlet sun sunw(它们都是在JSP白皮书中指定的保留字)之类的前缀         uri属性满足了以上的第二个要求 为每个自定义行为找到对应的类 这个uri包含了一个字符串 容器用它来定位TLD文件 在TLD文件中可以找到标签库中所有标签处理类的名称         当web应用程序启动时 容器从WEB INF文件夹的目录结构的META INF搜索所有以 tld结尾的文件 也就是说它们会定位所有的TLD文件 对于每个TLD文件 容器会先获取标签库的URI 然后为每个TLD文件和对应的URI创建映射关系         在JSP页面中 我们仅需通过使用带有URI属性值的标签库指令来和具体的标签库匹配         三 自定义JSP标签的处理过程        在JSP中引入标签库        在JSP中使用标签库标签        Web容器根据第二个步骤中的prefix 获得第一个步骤中声明的taglib的uri属性值        Web容器根据uri属性在web xml找到对应的元素 从元素中获得对应的元素的值 Web容器根据元素的值从WEB INF/目录下找到对应的 tld文件 从 tld文件中找到与tagname对应的元素 凑元素中获得对应的元素的值 Web容器根据元素的值创建相应的tag handle class的实例 Web容器调用这个实例的doStartTag/doEndTag方法完成相应的处理         四 创建和使用一个Tag Library的基本步骤        创建标签的处理类(Tag Handler Class)        创建标签库描述文件(Tag Library Descrptor File)        在web xml文件中配置元素 在JSP文件中引人标签库        五 TagSupport类简介        处理标签的类必须扩展javax servlet jsp TagSupport         TagSupport类的主要属性         A parent属性 代表嵌套了当前标签的上层标签的处理类         B pageContex属性 代表Web应用中的javax servlet jsp PageContext对象         JSP容器在调用doStartTag或者doEndTag方法前 会先调用setPageContext和setParent方法 设置pageContext和parent 因此在标签处理类中可以直接访问pageContext变量         在TagSupport的构造方法中不能访问pageContext成员变量 因为此时JSP容器还没有调用setPageContext方法对pageContext进行初始化

        六 TagSupport处理标签的方法        TagSupport类提供了两个处理标签的方法         public int doStartTag() throws JspException        public int doEndTag() throws JspException        doStartTag:但JSP容器遇到自定义标签的起始标志 就会调用doStartTag()方法         doStartTag()方法返回一个整数值 用来决定程序的后续流程         A Tag SKIP_BODY:表示?>…之间的内容被忽略         B Tag EVAL_BODY_INCLUDE:表示标签之间的内容被正常执行         doEndTag:但JSP容器遇到自定义标签的结束标志 就会调用doEndTag()方法 doEndTag()方法也返回一个整数值 用来决定程序后续流程         A Tag SKIP_PAGE:表示立刻停止执行网页 网页上未处理的静态内容和JSP程序均被忽略任何已有的输出内容立刻返回到客户的浏览器上         B Tag_EVAL_PAGE:表示按照正常的流程继续执行JSP网页         七 用户自定义的标签属性        如果在标签中还包含了自定义的属性 那么在标签处理类中应该将这个属性作为成员变量 并且分别提供设置和读取属性的方法         八 创建标签处理类的步骤        创建包含JSP网页静态文本的文件(即是要替换自定义JSP标签的文本)         在Web应用启动时装载静态文本         创建标签处理类         九 如何创建包含JSP网页静态文本的文件        使用java util Properties类来存放要替换网页中自定义JSP标签的静态文本         Properties类代表了一系列属性的集合 其实例既可以被保存到流中 也可以从流中加载 这些文本以key/value的形式存放在WEB INF目录下 例如key=value 在属性列表中这些key/value都是String类型的         十 Properties类的常用API        setProperty(String key String value) 调用Hashtable类的put方法添加属性         getProperty(String key) 获取属性列表中key对应的属性值         load(InputStream in) 从输入流对象InputStream中读取属性列表(Properties list)         store(OutputStream out String Ment) 使用适当的格式将属性列表的属性对写入输出流对象中 默认使用ISO 编码格式 以行的方式处理输入 属性的key/value之间以 = 配对 以回车 换行分隔key/value配对         十一 ServletContext类的常用API        getContext(String uripath) 返回服务器中uripath所代表的ServletContext对象         getInitParameter(String name) 返回ServletConfig对象中name参数的值         getMineType(String file) 返回file参数代表的文件的MIME类型         getRequestDispatcher(String path) 返回path代表的RequestDispacher对象         getResourceAsStream(String path) 以输入流的形式返回path对应的资源 在输入留中对象可以为任意形式的数据 path参数必须以 / 开始且相对于Context Root         十二 如何使用ServletContxt读取并保存属性文件        创建java util Properties类对象         获取ServletContext对象         将属性文件以输入流的形式读入到某个输入流对象中         将输入流对象加载到Properties对象中         将Properties对象保存到ServletContext对象中         十三 如何在Web应用启动时装载静态文本        创建继承了HttpServlet类的子类 在web xml中配置这Servlet时设置load on startup属性         someclass        somepackage SomeClass         在这个Servlet的init()方法中创建java util Properties类        获取当前Web应用的ServletContext对象        将WEB INF目录下的属性文件读入到输入流InputStream中         InputStream in = context getResourceAsString( WEB INF/someproperties properties )         将输入流加载到属性对象中        ps load(in)         将属性对象保存到上        context setAttribute( attributeName ps)         十四 如何创建标签处理类        引入必需的资源        import javax servlet jsp *import javax servlet *import java util *import java io *        继承TagSupport类并覆盖doStartTag()/doEndTag()方法        从ServletContext对象中获取java util Properties对象        从Properties对象中获取key对应的属性值        对获取的属性进行相应的处理并输出结果        十五 创建标签库描述文件(Tag Library Descriptor)        标签库描述文件 简称TLD 采用XML文件格式 定义了用户的标签库 TLD文件中的元素可以分成 类         A 标签库元素        B 标签元素        C 标签属性元素        标签库元素用来设定标签库的相关信息 它的常用属性有         A shortname:指定Tag Library默认的前缀名(prefix)         B uri:设定Tag Library的惟一访问表示符         标签元素用来定义一个标签 它的常见属性有         A name:设定Tag的名字         B tagclass:设定Tag的处理类         C bodycontent:设定标签的主体(body)内容         )empty:表示标签中没有body        )JSP:表示标签的body中可以加入JSP程序代码         )tagdependent:表示标签中的内容由标签自己去处理         标签属性元素用来定义标签的属性 它的常见属性有         A name:属性名称         B required:属性是否必需的 默认为false        C rtexprvalue:属性值是否可以为request time表达式 也就是类似于<%=…% >的表达式         十六 在Web应用中使用标签        如果Web应用中用到了自定义JSP标签 则必须在web xml文件中加入元素 它用于声明所引用的标签所在的标签库        /sometaglib        /WEB INF/someTLD tld        设定Tag Library的惟一标示符 在Web应用中将根据它来引用Tag Libray        指定和Tag Library对应的TLD文件的位置         在JSP文件中需要加入        prefix表示在JSP网页中引用这个标签库的标签时的前缀 uri用来指定Tag Library的标识符 它必须和web xml中的属性保持一致 lishixinzhi/Article/program/Java/hx/201311/25941

jsp自定义标签用法,供大家参考,具体如下:

什么是标记

使用HTML语言我们可以这样去编辑我们的网页:

<HTML>

<HEAD>

<TITLE>

HELLO WORLD

</TITLE>

</HEAD>

<BODY>

HELLO WORLD

</BODY>

</HTML>

在这里我们把</HEAD>,<TITLE>,<BODY>称为标记。HTML 标记( HTML Markup)是HTML文档的控制语言,用于指定浏览器显示和打印文档的方式.它是用小于号"<"和大于号">"括起来的短语和符号,如 <Html>、</Body>等。许多HTMl标记以成对的方式出现,如<TITLE></TITLE>、<Body></Body>等。在JSP中我们也可以定制自己的标记,以供JSP页面使用,如下例所示:

<!—login.jsp-->

<%@ taglib uri="/tlds/taglib.tld" prefix="tagclass" %>

<html>

<head>

<title>login</title>

</head>

<body>

<tagclass:login width="200" height= "100" >

</tagclass:login>

</body>

</html>

在上例中</tagclass:login>就是一个JSP定制标记符。widtht、height是这个标记的属性。<%@ taglib uri="/tlds/taglib.tld" prefix="tagclass" %>是一个标记库定义指令,在稍后我们将会讨论。在JSP中定制标记符,实质上就是以标记的形式封装了一个俱有独立功能的Java类。标记的使用减少了直接嵌入JSP页面的Java代码,方便了页面的布局,并且有利于代码的复用,提高了开发的效率。

JSP服务器解析标记的过程

那么当一个标记被嵌入JSP页面后,JSP服务器是如何对这个标记进行解析的呢?各对象的含义如下所示:

Client: 表示客户端。

JSP-Server:JSP服务器。

JSP-Page:JSP页面。

TLD: 标记库描述文件,定义标记和标记的各种属性和处理文件等。

TagClass 标记处理程序

当一个用户访问一个JSP页面时,这个请求被发送到JSP服务器,JSP服务器会根据这个请求去调用相应的页面,如果这个页面中有自定义的标记, JSP服务就会根据页面指令<%@ taglib>去访问TLD得到处理程序的相关信息,接着调用该处理程序的构造器方法,启动标记符处理程序,并读取标记符的属性和相应值。对每个没有设置属性的,调用相应的set方法。当标记符第一次使用时,它的任何属性都不会做过设置,因此对每个属性都调用set方法。属性设置完以后,JSP服务器调用处理程序的doStartTag(),然后再调用doEndTag()方法。最后JSP服务器会继续处理剩下的页面,在页面结尾调用release ()方法,清理占用的所有资源。

TLD文件

TLD(TLD:Tag Library Descriptor标记库描述符)文件,标准的XML格式的标记定义文件,被用来存放标记符的信息,下面就是一个典型的TLD文件。

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!—XML的版本及其字符集-->

<!DOCTYPE taglib

PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"

" http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<!—文档类型定义-->

<taglib>

<!—此标记说明我们开始描述一个标记库-->

<tlibversion>1.0</tlibversion>

<!—标记库的版本-->

<jspversion>1.1</jspversion>

<!—所使用的JSP的版本-->

<shortname>tagclass</shortname>

<!—缺省的名称-->

<tag>

<name>login</name>

<!—标记的名称-->

<tagclass>

tagclass.login.login

<!—处理这个Tag的相应的类的名称-->

</tagclass>

<info>

<!—对本标记符的描述-->

</info>

<attribute>

<!—开始定义标记的属性-->

<name>height</name>

<!—属性的名称-->

<required>true</required>

<!—表示这个属性是不是必须的-->

<rtexprvalue>true</rtexprvalue>

<!—表示这个属性是否可以用JSP的程序段的结果输出-->

</attribute>

<attribute>

<name>width</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>

</attribute>

</tag>

</taglib>

在这个TLD文件中定义了只有一个标记符的标记符库,这个名为login的标记符会调用一个Applet以验证用户的合法性。处理这个标记的类就是 tagclass.login.login。width、height是这个标记的两个属性。属性是在使用标记符时作为参数发送的值。我们可以在上面的示例中增加几个标记,也可以为每个标记添加几个属性。我们开发标记符库时不一定非要从头开始,自己编写一个全新TLD。我们可以使用某个集成的开发的环境,也可以修改上面的例子。

TagLib指令

那么当JSP服务器在解析一个标记符时,它是如何定义一个标记库的呢?这就是TagLib指令的主要责任。

Taglib 指令

定义一个标记库以及其自定义标记的前缀.

JSP 语法

复制代码 代码如下:

<%@ taglib uri="URIToTagLibrary" prefix="tagPrefix" %>

例子

<%@ taglib uri="/tlds/taglib.tld" prefix="tagclass" %>

<html>

<head>

<title>login</title>

</head>

<body>

<tagclass:login width="200" height= "100" >

</tagclass:login>

</body>

</html>

描述

<% @ taglib %>指令声明此JSP文件使用了自定义的标记,同时引用标记库,

也指定了他们的标记的前缀。 你必须在使用自定义标记之前使用<% @ taglib %>指令。

属性

uri="URIToTagLibrary" :Uniform Resource Identifier (URI)根据标记的前缀对自定义的标记进行唯一的命名,URI可以是一个相对或绝对的路径。

prefix="tagPrefix":在自定义标记之前的前缀。如上例中的</tagclass:login>

标记符的处理程序(Tag handle)

我们还是以一个例子来看下如何实现一个Tag handle。首先是看一下它的类图:

让我们再看一下它的代码:

package tagclass.login

import javax.servlet.jsp.tagext.TagSupport

import javax.servlet.jsp.*

import java.io.*

public class login extends TagSupport

{

public login()

{

super()

}

public int doStartTag() throws JspTagException

{

JspWriter out = pageContext.getOut()

try

{

out.println("<APPLET CODEBASE=applet/login/ CODE=login.class width=200 height=100 ></APPLET>")

}

catch(Exception e)

{

}

return SKIP_BODY

}

publicc int doEndTag()throws JsptagException

{

return EVAL_PAGE

}

public void release()

{

super.release()

}

public void setWidth(String language)

{

this.width = width

}

public String getWidth()

{

return this.width

}

public void setHeight(String height)

{

this.height=height

}

public String getHeight()

{

return this.height

}

private String width

private String height

}

从以上我们可以看出,实现一个简单的标记符处理程序有几个要求:①增加一个类,使之继承 java.Servlet.jsp.tagext.TagSupport类。这个类提供了java.Servlet.jsp.tagext.Tag接口所要求的所有的方法。另外,还需要使用一些基本的API,使JSP容器能够调用我们自己提供的标记符处理程序。②必须为每个标记符属性分别创建一个 get<attribute>和set<attribute>方法,JSP容器需要使用这些方法处理程序传递参数。③要为标记符处理程序创建一个构造器和自毁器。JSP需要使用构造器启动处理程序。自毁器是在realease()方法中定义的。在处理程序的生命周期结束时,需要调用自毁器释放所占用的资源。④创建两个名为doStartTag()和doEndTag()的方法,执行具体的处理和输出动作。这两个方法是在处理自定义标记符的起始位置和结束位置调用的。它们的返回值是在Tag Interface里定义的静态int,这几个静态值分别是:

SKIP_BODY隐含0 :跳过了开始和结束标签之间的代码。

EVAL_BODY_INCLUDE隐含1:将body的内容输出到存在的输出流中

SKIP_PAGE隐含5 : 忽略剩下的页面。

EVAL_PAGE隐含6:继续执行下面的页

当然标记符也有它自己的缺点。很不方便的封装过程,有限的功能。对于一些不太复杂和功能单一的逻辑描述,需要传递的参数要求不高时,使用JSP标记,要方便的多。对于大多数的商业逻辑应用,还是使用bean要好的多,也宜于servlet控制。

附:文章中所用示例的完整代码

JSP代码:login.jsp

<%@ taglib uri="/tlds/taglib.tld" prefix="tagclass" %>

<html>

<head>

<title></title>

</head>

<body>

<tagclass:login width="200" height= "100" >

</tagclass:login>

</body>

</html>

标记符描述库:taglib.tld

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE taglib

PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"

" http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<taglib>

<tlibversion>1.0</tlibversion>

<jspversion>1.1</jspversion>

<shortname>tagclass</shortname>

<tag>

<name>login</name>

<tagclass>

tagclass.login.login

</tagclass>

<info>

</info>

<attribute>

<name>height</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>

</attribute>

<attribute>

<name>width</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>

</attribute>

</tag>

</taglib>

标记符处理程序:login.java

package tagclass.login

import javax.servlet.jsp.tagext.TagSupport

import javax.servlet.jsp.*

import java.io.*

public class login extends TagSupport

{

public login()

{

super()

}

public int doStartTag() throws JspTagException

{

JspWriter out = pageContext.getOut()

try

{

out.println("<APPLET CODEBASE=applet/login/ CODE=login.class width=200 height=100 ></APPLET>")

}

catch(Exception e)

{

}

return SKIP_BODY

}

publicc int doEndTag()throws JsptagException

{

return EVAL_PAGE

}

public void release()

{

super.release()

}

public void setWidth(String language)

{

this.width = width

}

public String getWidth()

{

return this.width

}

public void setHeight(String height)

{

this.height=height

}

public String getHeight()

{

return this.height

}

private String width

private String height

}

标记符处理程序中所使用的Applet : login.java

import java.awt.*

import java.awt.event.*

import java.applet.*

public class login extends Applet implements ActionListener

{

private String s_username

private String s_userpassword

private Button b_ok

private Button b_register

private Label l_username

private Label l_userpassword

private TextField t_username

private TextField t_userpassword

private GridLayout g_gridlayout

public void init()

{

b_ok=new Button("ok")

b_register=new Button("register")

l_username= new Label("name")

l_userpassword=new Label("password")

t_username=new TextField()

t_userpassword=new TextField()

b_ok.addActionListener(this)

b_register.addActionListener(this)

g_gridlayout=new GridLayout(3,2,10,10)

this.setLayout(g_gridlayout)

//this.setBackground(Color.blue)

add(l_username)

add(t_username)

add(l_userpassword)

add(t_userpassword)

add(b_ok)

add(b_register)

}

public void actionPerformed(ActionEvent ev)

{

String s_label=ev.getActionCommand()

if (s_label.equals("ok"))

{

t_username.setText("name")

}

if (s_label.equals("register"))

{

t_userpassword.setText("password")

}

}

public void paint(Graphics g)

{

}

}

JSP标签有两种实现方法,一种是使用tag 文件,一种是使用tld文件。

1、使用tag文件

标签名和tag文件名一致, tag文件为JSP文件,可以有属性,把JSP页面当JavaBean文件一样使用。

例子:

1)WEB-INF/lib下放置TAG文件:MyTag.tag,那么就有了一个名为MyTag的标签:

<%@ tag pageEncoding="UTF-8" %>  

<%@ attribute name="id" required="true" rtexprvalue="true" %>  

<%@ attribute name="webletID" required="true" rtexprvalue="true" %>  

  

<B>JSP TAG ATTRIBUTE GET<B>  

  

<div id="<%=getId() %>" style="border:solid 1px #ff0000">  

    Here, got the attribute value by get method:<%=getWebletID() %>  

    <br>Got the attribute value by variable:<%=webletID %>  

</div>  

  

<script>  

  

</script>  

<br>

可定义属性attribute,有变量名(name),是否必需(required)等属性,相当于定义一个JavaBean的属性。在使用属性的值时,可通过get方法来访问或通过变量名的方式来访问。

2)创建引用标签的JSP文件test.jsp,放置于Web目录下,如何WEB-INF同级目录

[html] view plain copy

<%@ page language="java" contentType="text/html charset=UTF-8" pageEncoding="UTF-8"%>  

<%@ taglib prefix="mx" tagdir="/WEB-INF/tags"%>  

<html>  

<head>  

<meta http-equiv="Content-Type" content="text/html charset=GBK" />  

    <title>Tag test</title>   

</head>  

  

<body>  

    <h1>Tag Test is ok!</h1>  

  

    <mx:MyTag id="Weblet1" webletID="W1001"/>  

</body>  

  

</html>

在定义好属性后,就可在TAG被引用时,接受传入参数。标签TAG的属性id,webletID。

3)访问test.jsp,效果如下:

JSP TAG ATTRIBUTE GET

Here, got the attribute value by get method:W1001 

Got the attribute value by variable:W1001

2、使用tld文件

tld为XML格式文件,在其中描述标签组件的类和属性等。

方法1的使用比较直接简单,修改标签直接修改JSP文件即可;方法2使用定义方式来描述标签,修改标签需要修改tld描述文件和对应的class文件。

JSP中的TAG文件和TLD文件小结

在jsp文件中,可以引用tag和tld文件。 

1.对于tag文件 

<%@ taglib prefix="ui" tagdir="/WEB-INF/tags" %> 

其中的tags是个目录,里面有若干tag文件。 

但使用<ti:XXXX>时,目录WEB-INF/tags下,必然有个XXXX.tag文件与之对应。

2.对于tld文件 

在jsp中可以引用TLD文件,如 

<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>

但是这个http://struts.apache.org/tags-html对应着什么呢?

jsp会在当前目录的\WEB-INF下找所有tld文件,确认这个URL对应哪个TLD文件。 

当找到struts-html.tld文件时,发现其中的内与这个URL对应。 

但使用<html:YYYYY>时,这个TLD文件中必然有个YYYY项与之对应。 

还有一种更保险的方法是,在WEB-INF/web.xml中加上 

<taglib> 

    <taglib-uri> 

http://jakarta.apache.org/tomcat/examples-taglib 

    </taglib-uri> 

    <taglib-location> 

       /WEB-INF/jsp/example-taglib.tld 

    </taglib-location> 

</taglib>

这样表示http://jakarta.apache.org/tomcat/examples-taglib对应着/WEB-INF/jsp/example-taglib.tld

tag文件作用一般是一段小代码,类似include文件的作用。 

tld文件作用比较复杂,可以实现很多高级的作用。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11870627.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-19
下一篇 2023-05-19

发表评论

登录后才能评论

评论列表(0条)

保存