Cui.Liqiang

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

      最近在做chronicles的java项目。发现自己java web相关各种技术都比较稀松。于是给自己列了个列表,把不会的,需要加强的东西都写上去,再一点一点看。然后把学习的成果做些许记录。本文主要讲JSP标签的工作原理。首先看一个JSP文件:

jsp code
1  <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
2 <%@ taglib uri = "http://java.sun.com/jsp/jstl/core"; prefix = "c"%>
3 <%@ taglib prefix = "fn" uri = "http://java.sun.com/jsp/jstl/functions"%>
4
5 <div id="ajax_wrapper">
6
7 <c:if test="${fn:length(story_view_models) == 52}">
8 <div id="swap_story_message">You already have 52 stories, so we will be swapping stories.</div>
9 </c:if>
10 <span id="${id_for_tip}">Drag the story here to add to the 52 week list...</span>
11
12 <div id="approved_stories_container">
13 <c:forEach items="${story_view_models}" var="model">
14 <div><span>${model.storyTruncatedTitle}</span><input type="hidden" value="${model.id}"/></div>
15 </c:forEach>
16 </div>
17 <div id="numbering_for_approved_stories_container">
18 </div>
19 </div>

  形如上面的jsp代码在第2,3行使用taglib标签引入了一些标签库,并分别定义了他们的前缀为c和fn。然后就可以使用c:forEach等标签写嵌入式的脚本了。但是这写标签是怎么工作的呢。在Intellij中使用command+B到了这些标签的定义文件,发现是一个tld文件,如下:

taglib的tld文件
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <taglib xmlns="http://java.sun.com/xml/ns/j2ee";
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
4 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd";
5 version="2.0">
6
7 <description>JSTL 1.1 core library</description>
8 <display-name>JSTL core</display-name>
9 <tlib-version>1.1</tlib-version>
10 <short-name>c</short-name>
11 <uri>http://java.sun.com/jsp/jstl/core</uri>;
12
13 <validator>
14 <description>
15 Provides core validation features for JSTL tags.
16 </description>
17 <validator-class>
18 org.apache.taglibs.standard.tlv.JstlCoreTLV
19 </validator-class>
20 </validator>
21
22 <tag>
23 <description>
24 Simple conditional tag that establishes a context for
25 mutually exclusive conditional operations, marked by
26 :when and otherwise.
27 </description>
28 <name>choose</name>
29 <tag-class>org.apache.taglibs.standard.tag.common.core.ChooseTag</tag-class>
30 <body-content>JSP</body-content>
31 </tag>
32 ................
33 </taglib>

  这里只粘了一个标签,即choose的定义上来,可以看到除了名字和描述之外,每个标签都对应了一个java类。当你这些标签所起的作用也就在这些类中定义了。具体这些java代码是如何写的可以参看此链接。因此自己也可以写一些自定义的标签库,如果有必要。所以一个jar包+一个tld文件就定义了一个标签库。
  上面提到了jsp文件中通过下面的代码引入taglib:
  <%@ taglib prefix = "fn" uri = "http://java.sun.com/jsp/jstl/functions"%>
  即通过uri来定位tld文件,可是这样的一个打到浏览器就会转向到oracle网站而且什么标签信息都获得不到的的url怎么就能够帮助我么找到tld文件呢?答案是在web.xml中进行配置。通常会在web.xml中有一个taglib的定义。如下:

1 <taglib>
2 <taglib-uri>
3 http://www.example.com/taglib
4 </taglib-uri>
5 <taglib-location>
6 /taglib.tld
7
8 </taglib-location>
9 </taglib>

  这就相当于给这个有意义的硬盘路径“/taglib.tld”了一个别名,也就是那个看似url的uri。然后就可以在jsp中引用了。但是我看chronicles的代码是,发现web.xml中并没有这样的定义。如是甚是纳闷。今天找了一天终于找到了答案。回到上面的tld文件,可以看到这样一行:

 

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

  这个tld文件是包含在一个叫做standard.jar的文件中的,该jar包放到了web/lib下,也就是放到了classpath下面。打开jar文件发现有两个文件夹:org, META-INF。第一个当然就是package名了,在第二个文件里包含了一大堆tld文件。每个tld都有uri这个标签来指定一个uri。于是可以大概猜测,jsp文件扫描classpat下的所有META-INF文件夹找里面的tld文件,如果遇到uri匹配的就指定该文件。然后做了个实验,把standard.jar解压,改变里面的uri标签,比如对于该例,把 http://java.sun.com/jsp/jstl/core 改成 http://java.sun.com/jsp/jstl/cor 。然后再打包替换原来的文件。再到intellij里面看jsp文件里引用taglib的那些代码都红了,也就是说找不到了。再把引用的那个uri变成跟我在jar包里修改的一样,即http://java.sun.com/jsp/jstl/cor,就ok了。

  再做两个令人发指的实验,把tld文件拷出来,分别放到和META-INF平级的目录下和org目录下,竟然也都能找到。看到它搜索的范围还真不小。所以结论是jsp会在所有的classpath及其所有子目录下进行去搜索。那么classpath下有很多jar包的时候扫描会不会特别慢,或者有一些索引缓存机制吧。

posted on 2010-10-31 13:36  Cui.Liqiang  阅读(2257)  评论(1编辑  收藏  举报