自定义标签tld的使用

在JSP中使用标签是很平常的事情,在制作自定义标签时,通常都需要写tld文件来定义标签的各种属性,对应的Java类,前缀等等。标签与tld文件紧紧相连,那么,到底应该怎么放置tld文件?在web.xml中怎么定义tld文件的位置?

以下是具体的分析

Taglib的使用:

首先是在头部申明taglib, uri必须是web.xml定义的,或者是原始tld文件定义的。

<%@ taglib prefix="c"uri="http://java.sun.com/jstl/core" %>

<%@ taglib prefix="ex"uri="/jstl-examples-taglib" %>

然后便可以在jsp页面中通过prefix使用相应的标签

<c:import varReader="reader"url="${filepath}">

<ex:escapeHtmlreader="${reader}"/>

</c:import>

Uri与tld文件的映射关系

JSP文件中使用的标签通常都有一个tld定义文件(标签库定义文件,主要定义标签对应的java类,标签的属性等等信息)与之对应的,web容器需要找到相应的tld文件,以tld文件中定义的内容判断标签的使用是否正确。

Web做【使用正确性】判断处理,当遇到类似【<c:import】这样的标签时,会通过prefix定位到uri,再根据uri定位到相应的tld文件,对tld文件进行解析。其中urißàtld文件的映射关系如下:

Key

(Uri)

Value

(String[] taglib_tld_location)

Taglib-URI:

(如/jstl-examples-taglib、http://java.sun.com/jstl/core等)

taglib_tld_location[0]

taglib_tld_location[1]

本文主要介绍的便是uri到tld的映射

Tld文件路径定义方式

如下方式1和方式2只能在2.3版本使用,Servlet2.4开始便不能在web.xml中定义taglib了。

<!DOCTYPE web-app

PUBLIC "-//SunMicrosystems, Inc.//DTD Web Application 2.3//EN"

"http://java.sun.com/dtd/web-app_2_3.dtd">

l  方式1:

如下所示,在web.xml中定义

<taglib>

<taglib-uri>/jstl-examples-taglib</taglib-uri>

<taglib-location>/WEB-INF/lib/jstl-examples.tld</taglib-location>

</taglib>

如果这样定义的话,映射关系便如下:

/jstl-examples-taglibßà{“/WEB-INF/lib/jstl-examples.tld”,””} // taglib_tld_location[0]就足以表示tld路径,因此taglib_tld_location[1]为空。

l  方式2:

如下所示,在web.xml中定义

<taglib>

<taglib-uri>/jstl-examples-taglib</taglib-uri>

<taglib-location>/WEB-INF/lib/jstl-examples.jar</taglib-location>

</taglib>

如果这样定义的话,映射关系便如下:

/jstl-examples-taglibßà{“/WEB-INF/lib/ jstl-examples.jar”,” META-INF/taglib.tld”}

// taglib_tld_location[0]表示jar路径,taglib_tld_location[1]固定为META-INF/taglib.tld(也就是说,tld在jar文件中的保存路径必须是META-INF/taglib.tld,名称必须是taglib.tld)。这就是说一个jar里只能有一个tld。如果代码中不固定为taglib.tld的话,也很难处理,因为如果tld的名称可以随便定义的话,出现多个tld在jar文件中时将会导致混乱。

l  方式3:

不需要在web.xml中定义,只需要把tld保存在web应用能够使用的jar文件中的META-INF路径下便可。这种情况的机制是这样的:web容器会遍历当前web应用能够访问的jar文件,从jar文件中查找META-INF/xxx.tld文件,当找到一个tld文件之后,便会解析tld文件,取出<taglib>节点的<uri>值,把uri作为key值生成映射关系。

如下所示的jstl的core标签库的tld文件,便会有如下的映射关系

http://java.sun.com/jstl/coreßà{“tld文件所在的jar文件的路径”,” META-INF/xxx.tld”}//taglib_tld_location[0]表示jar路径,taglib_tld_location[1]为所搜到的tld在jar文件中的相对路径

……

<taglib>

<tlib-version>1.0</tlib-version>

<jsp-version>1.2</jsp-version>

<short-name>c</short-name>

<uri>http://java.sun.com/jstl/core</uri>

<display-name>JSTLcore</display-name>

<description>JSTL 1.0 corelibrary</description>

……

<tag>

<name>catch</name>

<tag-class>org.apache.taglibs.standard.tag.common.core.CatchTag</tag-class>

<body-content>JSP</body-content>

<description>

Catchesany Throwable that occurs in its body and optionally

exposesit.

</description>

<attribute>

<name>var</name>

<required>false</required>

<rtexprvalue>false</rtexprvalue>

</attribute>

</tag>

……

Ø  Tld文件的解析逻辑

以jstl为例:

Web容器遇到类似【<c:import】标签时,就会通过在头部中定义的<%@ taglib prefix="c"uri="http://java.sun.com/jstl/core" %>找到uri,再根据此uri便可以定位到taglib_tld_location。当taglib_tld_location[0]不是jar文件时,便直接使用java的FileInputStream读取tld文件;当taglib_tld_location[0]是jar文件时,则会

通过如下代码读取tld文件。

URL jarFileUrl = new URL("jar:" +location[0] + "!/");

ZipEntry jarEntry = jarFile.getEntry(location[1]);

Ø  总结:

Tld的定义可以不在web.xml中定义,这时需要保证tld在web应用能够访问的jar中,并且保存在jar的META-INF目录下。此时JSP直接使用tld中定义的<uri>便可;

如果在web.xml中定义tld的路径的话,可以直接指定tld文件路径,此时要保证tld不在jar包中(比如在WEB-INF目录下);也可以指定为jar文件路径,此时要保证tld在jar中且路径为META-INF/taglib.tld。

在web.xml中定义的uri优先级要高于tld文件中定义的优先级。

===============================================================

jsp自定义标签 Tag文件版

实现一个与上篇文章类似的Select标签功能
1.在WEB-INF/tags/select.tag

<%@ tag body-content="empty" %>
<%@ tag dynamic-attributes="tagAttrs" %>
<%@ attribute name="optionsList" type="java.util.List" required="true" rtexprvalue="true"%>
<%@ attribute name="name" required="true"%>
<%@ attribute name="size" required="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>

<select name="${name }" size="${size }"
   <c:forEach var="attrEntry" items="${tagAttrs }">
     ${attrEntry.key}="${attrEntry.value }"
   </c:forEach>
>
   <c:forEach var="option" items="${optionsList}">
     <option value="${option }">${option}</option>
    </c:forEach>
 </select>
这里要注意tag文件只能放在如下位置:
1.WEB-INF/tags
2.WEB-INF/tags的子目录
3.WEB-INF/lib中jar包的META-INF/tags
4.WEB-INF/lib中jar包的META-INF/tags下的子目录
5.jar包中的tag文件需要tld
添加jstl.jar与standard.jar到WEB-INF/lib目录,还有一点就是上面标红的部分:不要使用http://java.sun.com/jstl/core这个url,否则会报foreach中的item属性有问题

2.在jsp中的使用

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<%@ taglib prefix="formTag" tagdir="/WEB-INF/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
 List<String> colorList = new ArrayList<String>();
    colorList.add("red");
    colorList.add("blue");
    colorList.add("white");
    request.setAttribute("colorList",colorList);
%>

<form action="" method="post">
 <formTag:select name="color" size="1" optionsList="${requestScope.colorList}"  style="width:140px"/>
</form>
</body>
</html>

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

jsp 自定义标签

jsp标签有两组api
JspTag ->SimpleTag ->SimpleTagSupport
JspTag ->Tag ->IterationTag->BodyTag
第二组是classic的,比较早的使用方式,doStartTag(),doEndTag()有N多返回值的那种,使用起来也确实不方便,今天学到了另一个使用第一组api方式的,让人大快人心,贴码
例子是一个Select的标签,支持动态属性设置
1.编写标签类

public class SelectTagHandler extends SimpleTagSupport implements DynamicAttributes {
 private static final String ATTR_TEMPLATE = "%s='%s'";
 private static final String OPTION_TEMPLATE = "<option value='%1$s'>%1$s</option>";
 private List optionsList;
 private String name;
 private String size;
 private Map<String, Object> tagAttrs = new HashMap<String, Object>();

public void setName(String name) {
  this.name = name;
 }

public void setSize(String size) {
  this.size = size;
 }

public void setOptionsList(List optionsList) {
  this.optionsList = optionsList;
 }

@Override
 public void doTag() throws JspException, IOException {
  PageContext pageContext = (PageContext) getJspContext();
  JspWriter out = pageContext.getOut();
  out.print("<select ");
  out.print(String.format(ATTR_TEMPLATE, "name", this.name));
  out.print(String.format(ATTR_TEMPLATE, "size", this.size));
  for (String attrName : tagAttrs.keySet()) {
   String attrDefinition = String.format(ATTR_TEMPLATE, attrName, tagAttrs.get(attrName));
   out.print(attrDefinition);
  }
  out.print(">");

for (Object option : this.optionsList) {

String optionTag = String.format(OPTION_TEMPLATE, option.toString());
   out.println(optionTag);
  }
  out.println("</select>");
 }

@Override
 public void setDynamicAttribute(String uri, String name, Object value) throws JspException {
  tagAttrs.put(name, value);
 }
}
看到没,代码如此的简洁,动态属性配置也十分的方便,不用写N多个setter与getter方法.

2.编写tld文件WebRoot/tld/select.tld

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

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3g.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"
version="2.0">
 <tlib-version>1.2</tlib-version>
 <jsp-version>1.2</jsp-version>
 <short-name>Forms Taglib</short-name>
 <uri>http://hi.baidu.com/tags/forms</uri>
 <description>
  An example tab library of replacements for the html form tags.
 </description>
 
 <tag>
  <name>select</name>
  <tag-class>com.baidu.hi.tag.SelectTagHandler</tag-class>
  <body-content>empty</body-content>
  
  <attribute>
   <name>optionsList</name>
   <required>true</required>
   <rtexprvalue>true</rtexprvalue>
   <type>java.util.List</type>
  </attribute>
  
  <attribute>
   <name>name</name>
   <required>true</required>
  </attribute>
  
  <attribute>
   <name>size</name>
   <required>true</required>
  </attribute>
  
  <dynamic-attributes>true</dynamic-attributes>
 </tag>
</taglib>

3.在jsp中的使用

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ page import="java.util.*" %>
<%@ taglib  prefix="formTags"  uri="/tld/select.tld"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<%@page import="java.util.ArrayList"%><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
 List<String> colorList = new ArrayList<String>();
    colorList.add("red");
    colorList.add("blue");
    colorList.add("white");
    request.setAttribute("colorList",colorList);
%>
<form action="" method="post">
 <formTags:select name="color" size="1" optionsList="${requestScope.colorList}" style="width:140px"/>
</form>
</body>
</html>

上一篇:JSP中重定向页面没有全屏显示的问题解决


下一篇:hdu-1052(贪心)