JSP标签工作原理

      最近在做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包的时候扫描会不会特别慢,或者有一些索引缓存机制吧。

你可能感兴趣的:(工作原理)