前言:
你把Web应用中的东西放在哪里?
容器会在哪里找web应用的东西?
客户怎么请求web应用中的东西?
首先带着前面的问题,先说说要成功的部署一个应用,需要遵循的目录结构(如下图)有一些注意事项:
WEB-INF一定要直接放在应用上下文之下(这个例子中,应用上下文就是“MyTestApp”)。“classes”目录必须直接放在“WEB-INF”目录中。“classes”目录中必须是类的包结构。“lib”目录要直接置于“WEB-INF”目录之下,JAR文件必须放在“lib”中。“META-INF”目录必须是JAR中的顶级目录,JAR中的TLD文件要放在“META-INF”目录下的某个位置(可以在任何子目录中,目录名不必是“TLDs”)。不在JAR中的TLD必须放在“WEB-INF”下的某个位置。标记文件(扩展名为.tag或.tagx的文件)必须放在“WEB-INF/tags”下的某个地方(除非部署在一个JAR中,如果是这样,这些TLD必须放在“META-INF/tags”下的某个位置)。
WAR文件
web应用的目录结构要求很严,各个内容只能放在该放的地方,所以移动一个web应用是让人很头疼的一件事情。而应对这种方法,就有了WRA文件的诞生。WAR文件,代表web归档,这是一个web应用结构的快照,采用了一种更可移植的压缩形式(它实际上就是一个JAR文件)。
建立WAR文件时,就是把整个Web应用结构(去掉web应用上下文目录,也就是把WEB-INF之上的一级目录去掉)压缩起来,并指定一个.war的扩展名。如果没有包括特定的web应用目录(例如:BeerApp),容器如何发现web应用的名/上下文呢?在Tomcat中,WAR文件的文件名就会成为web应用的名字!
注:不论web应用是否部署在一个WAR中,几乎没有任何区别!唯一一个重要的区别是WAR文件在web应用上下文下有一个“META-INF”目录(对应于”WEB-INF目录”),如下图红色的部分。
客户在浏览器中输入资源的路径,服务器就会返回这个资源。但是只要把文件放在WEB-INF下就能避免直接访问,或者如果应用部署为一个WAR文件,可以把不允许直接访问的文件放在META-INF下。
如果服务器得到的客户请求需要WEB-INF或META-INF下的文件,容器一定会响应一个404 NOT FOUND错误!
Servlet映射
每个servlet映射都有两部分,servlet元素与servlet映射元素,servlet元素中定义了一个servlet名和类,servlet映射元素中定义了映射至一个servlet名(在DD中的另外某个位置上定义的)的URL模式。
利用servlet映射,要组织建立两个结构:实际的物理目录和文件结构,这也是web应用资源所在的具体结构,还有一个是虚拟/逻辑结构。DD中的URL模式不会映射到DD中的servlet-name元素以外的其他元素。servlet-name元素是servlet映射的键,它们把请求url-pattern映射到具体的servlet类。
要点;客户按url-pattern请求servlet,而不是按servlet-name或者servlet-class!
三种<url-pattern>
元素:
①完全匹配:
<url-pattern>/Beer/SelectBeer.do</url-pattern>
必须以一个斜线(/)开头,可以有扩展名,但不必要。
②目录匹配:
<url-pattern>/Beer/*</url-pattern>
必须以一个斜线(/)开头,中间可以是一个虚拟目录或者实际目录,总是以一个斜线加星号(/*)结束。
③扩展名匹配:
<url-pattern>*.do</url-pattern>
必须以一个星号(*)开头(不能以斜线开头),星号的后面必须有一个点加扩展名(.do,.jsp等)。
容器在查找的时候,首先查找完全匹配,如果找不到完全匹配,再查找目录匹配,如果目录匹配也找不到,就查找扩展名匹配。当一个请求与多个目录<url-pattern>
匹配,容器会选择最长的匹配。例如,如果请求/foo/bar/myStuff.do,它就会映射到<url-pattern>
/foo/bar/,尽管这个要求与<url-pattern>
/foo/也匹配,但是前者更长一些,总是取最特定的匹配。
要点: