關于taglib中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:escapeHtml reader="${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 "-//Sun Microsystems, 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>JSTL core</display-name>
<description>JSTL 1.0 core library</description>
……
<tag>
<name>catch</name>
<tag-class>org.apache.taglibs.standard.tag.common.core.CatchTag</tag-class>
<body-content>JSP</body-content>
<description>
Catches any Throwable that occurs in its body and optionally
exposes it.
</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。
以前用WSAD wizard做的,都可以在JSP頁面中解析到EL表達式,當然前提是JSP2.0的情況下。
今天遇到了一個莫名其妙的問題。剛下載Eclipse3.3+MyEclipse6.0體驗的過程中,遇上了解析不到EL表達式的問題。經過好幾個小時的琢磨終于發現了,給大家share一下:
問題就出在建Web Project的時候web.xml聲明上。
web.xml聲明部分一般分為如下版本的xsd,
web-app_2_2.xsd
web-app_2_3.xsd
web-app_2_4.xsd
web-app_2_5.xsd
更詳細的列出各版本web.xml聲明部分吧,如下:
web-app_2_2.xsd
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/dtd/web-app_2_2.dtd">
web-app_2_3.xsd
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
web-app_2_4.xsd
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
web-app_2_5.xsd
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
確定web.xml里的xsd版本之后一定要在JSP的聲明(<%@page %>)部分加一行,如下:
<%@ page isELIgnored="false" %>
這樣設為false才能解析EL表達式。
經過各版本的test之后....
注意!! 其中servlets 2.4(我沒記錯的話JSP 2.0出來之后的第一個版本),這個版本的isELIgnored默認設置為false。所以使用web.xml里用web-app_2_4.xsd聲明的時候在JSP頁面不用特意聲明。
下面是官方Documention中isELIgnored Attribute的詳解:
The isELIgnored Attribute
• Format
– <%@ page isELIgnored="false" %>
– <%@ page isELIgnored="true" %>
Purpose
– To control whether the JSP 2.0 Expression Language
(EL) is ignored (true) or evaluated normally (false).
• Notes
– If your web.xml specifies servlets 2.3 (corresponding to
JSP 1.2) or earlier, the default is true
• But it is still legal to change the default—you are permitted
to use this attribute in a JSP-2.0-compliant server
regardless of the web.xml version.
– If your web.xml specifies servlets 2.4 (corresponding to
JSP 2.0) or earlier, the default is false
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/qingkangxu/archive/2010/12/05/6057034.aspx