您的位置:首页 > 其它

servlet的映射问题 和 转发与重定向的区别

2010-07-05 12:46 239 查看
还是转帖
1。来自http://diegoball.javaeye.com/blog/248724

Servlet映射地址形式

众所周知,Servlet在编写完毕后,必须先在web.xml中配置才能访问。在配置时,需要指定一个Servlet的访问地址。Servlet映射地址不是随便怎么写都可以,必须要遵从一定的规则,这个规则在Servlet的规范中有详细的说明。按照Servlet规范的要求,Servlet映射地址形式只能有四种,即:

  第一种、以“/”开头,以“/*”结束的地址,这种地址映射称为路径映射。这种映射中使用了通配符,代表访问这个目录下的任意一个地址都将调用这个Servlet。比如,一个Servlet映射的地址是“/admin/*”,那么当访问/admin这个目录下的任意一个地址,都会映射到这个Servlet上,除非这个地址已经明确地映射到其它的Servlet上了。也即,当另外一个Servlet映射的地址是“/admin/listUser”,那么当访问这个地址时,请求还是会被映射到这人Servlet上。

  第二种、以“*.”开头的地址,这种地址映射称为扩展名映射。这也是一种模糊映射,代表访问相同扩展名的地址时,都会映射到这个Servlet上。这种地址映射在Struts中就得到了应用,即所有访问以.do结束的地址时,都会映射到ActionServlet上。但不能将第一种与第二种地址映射形式结合起来用,即如果写成“/admin/*.do”,这就错了。没有原因,因为这是规范。

  第三种、只有一个“/”的地址映射,这种地址映射称为默认映射。也就是说,如果用户访问了一个地址,这个地址没有明确地在web.xml中映射,也不满足以上两种形式的模糊映射,这个时候就访问“/”映射的Servlet。这种地址映射,我们在实际开发中很少应用,但它对服务器来说是很重要的。以Tomcat为例,Tomcat实际上是一个纯粹的Servlet容器,也就是说,只有Servlet才能在Tomcat上运行。但有可能会说,我们将HTML文件部署到Tomcat上也运行得很好啊。没错,但真正运行的还是Servlet。什么意思呢?大家可以想一下,我们部署到服务器上所有的HTML文件,我们从来都不会到web.xml中去映射的,根据我们刚刚讲到的,如果访问了没有映射的地址,服务器会访问“/”所对应的Servlet,而正是这个Servlet帮我们找到HTML文件,并把它写到客户端的。也就是说,Tomcat预先定义了一个Servlet,并把它的地址映射为“/”。这样其它静态资源的访问实际上都是在访问这个Servlet,而它的职责则是简单地找到这个文件,并把它们写到响应中去。

  第四种、明确的地址映射,这是我们最常用的一种地址映射形式。规范中没有对这种地址映射有特殊的要求,但在配置地址时,必须以“/”开头才可以,否则将报错。

  总结以上几种地址形式,我们可以了解到服务器在接收到一个地址请求后的处理流程。以一个用户访问http://www.sodii.com/class_intro/viewClassIntro.htm?id=1这个地址为例:

  第一步,服务器首先看/class_intro/viewClassIntro.htm这个地址有没有明确地映射,如果已经明确地映射了这个地址,则直接访问地址所对应的Servlet,处理请求生成响应。
  第二步,如果没有明确映射这个地址,则看目录映射或扩展名映射中有没有满足这个地址的。也即有没有映射地址为“/class_intro/*”,或者“*.htm”的Servlet,如果有一个满足就访问其所对应的Servlet。如果两个都满足,则访问目录映射所对应的Servlet。
  第三步,如果也不满足模糊映射,则访问“/”所对应的Servlet。



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

2。 来自:http://www.javaeye.com/topic/39332

Servlet和Filter的url匹配以及url-pattern详解<o:p></o:p>

Servlet和filter是J2EE开发中常用的技术,使用方便,配置简单,老少皆宜。估计大多数朋友都是直接配置用,也没有关心过具体的细节,今天遇到一个问题,上网查了servlet的规范才发现,servlet和filter中的url-pattern还是有一些文章在里面的,总结了一些东西,放出来供大家参考,以免遇到问题又要浪费时间。<o:p></o:p>

一,servlet容器对url的匹配过程:<o:p></o:p>

<o:p></o:p>

当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如我访问的是http://localhost/test/aaa.html,我的应用上下文是test,容器会将http://localhost/test去掉,剩下的/aaa.html部分拿来做servlet的映射匹配。这个映射匹配过程是有顺序的,而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了(filter不同,后文会提到)。其匹配规则和顺序如下:<o:p></o:p>

1. 精确路径匹配。例子:比如servletA 的url-pattern为 /test,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先 进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,也不会去理会其他的servlet了。<o:p></o:p>
2. 最长路径匹配。例子:servletA的url-pattern为/test/*,而servletB的url-pattern为/test/a/*,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB。<o:p></o:p>
3. 扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet。例子:servletA的url-pattern:*.action<o:p></o:p>
4. 如果前面三条规则都没有找到一个servlet,容器会根据url选择对应的请求资源。如果应用定义了一个default servlet,则容器会将请求丢给default servlet(什么是default servlet?后面会讲)。<o:p></o:p>
根据这个规则表,就能很清楚的知道servlet的匹配过程,所以定义servlet的时候也要考虑url-pattern的写法,以免出错。<o:p></o:p>
对于filter,不会像servlet那样只匹配一个servlet,因为filter的集合是一个链,所以只会有处理的顺序不同,而不会出现只选择一个filter。Filter的处理顺序和filter-mapping在web.xml中定义的顺序相同。<o:p></o:p>

二,url-pattern详解<o:p></o:p>

在web.xml文件中,以下语法用于定义映射:
l 以”/’开头和以”/*”结尾的是用来做路径映射的。
l 以前缀”*.”开头的是用来做扩展映射的。
l “/” 是用来定义default servlet映射的。
l 剩下的都是用来定义详细映射的。比如: /aa/bb/cc.action
所以,为什么定义”/*.action”这样一个看起来很正常的匹配会错?因为这个匹配即属于路径映射,也属于扩展映射,导致容器无法判断。
----------------------------------------------------------------------------------------------------------------------------------

3。 来自:http://diegoball.javaeye.com/blog/248722



转发与重定向的区别

转发与重定向的区别,这在求职中是一个经常被问到的问题。所谓转发,实际上是指下面这条语句:

   request.getRequestDispatcher("某地址").forward(request, response);

  它能将请求由一个Servlet转到另外一个Servlet,或者在JSP页面之间转向。另一种用得比较多的是重定向,它的代码如下:

  response.sendRedirect("某地址");

  从本质上来说,它们的区别在于是否生成响应。上面那句话在执行时,实际上是生成了一个临时响应,这个响应是一个用户无法看到的响应,状态码是300。浏览器在接收到这个响应后,不显示任何东西,而再次发出一个请求到重定向的响应所指定的地址上。因此,用户最后看到的最后结果并不是第一次请求过的地址,而是重定向后的地址产生的结果。而请求的转发则不同,它是将请求交给另外一个Servlet来处理,然后处理好的结果还是由原来的Servlet返回。

  在讲到这里时,我经常举的一个例子是买白菜的例子。

  我是一个程序员,但是你不知道,以为我是卖白菜的,来找我买白菜。那么,我有两种选择,一是我去菜市场找个卖白菜,一毛钱买进来,然后再两毛钱卖给你。在这个过程中,你自始至终都是跟我一个人打交道,你并不知道菜农的存在;二是我直接告诉你,你找错人了,你应该去找菜农,然后你找到菜农,也买到了白菜。

  在这个例子中,前者就是请求的转发,后者就是响应的重定向。前者是一个请求“买菜”,一个响应“菜给你”,但菜怎么来的你不用管。后者是两次请求,两次响应。先请求一次,然后响应告诉你找错了人,接下来再请求正确的人,最后直接拿到结果。

  总结一下,它们的区别有三点:
1、是否生成响应;
2、地址栏是否发生变化;
3、是否在同一个请求作用域中



///////////////////////////////////////////////////////////////////////////////////////////////////////



以下是我的实验结果:

映射时:

若是 /test

则路径为:

localhost:8080/projectName/test

而且 此时映射不能为 test(不加/) 这样子tomcat启动时 是会报严重错误的



映射时:

若是 *.do(没有/开头)

则路径为:

localhost:8080/projectName/test.do

localhost:8080/projectName/sdfasdfsadfsdf.do (也就是说 只要是****.do就行 甚至可以直接.do)

而且 此时映射不能为/*.do 这样子tomcat启动时也是会报严重错误的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: