servlet映射URL模式中/和/ *之间的区别


175

熟悉的代码:

<servlet-mapping>
    <servlet-name>main</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>main</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

我的理解是,/*映射到http://host:port/context/*

怎么/样 它肯定不会http://host:port/context仅映射到root。实际上,它将接受http://host:port/context/hello,但拒绝http://host:port/context/hello.jsp

谁能解释如何http://host:port/context/hello映射?

Answers:


268

<url-pattern>/*</url-pattern>

/*上一个servlet覆盖所有其他的servlet,包括由servletcontainer提供诸如默认的servlet和JSP的servlet所有servlet。无论您发出什么请求,它都将最终出现在该servlet中。因此,这对于servlet是错误的URL模式。通常,您想/*Filter只想。通过调用,可以让请求继续到任何servlet侦听更特定的URL模式FilterChain#doFilter()

<url-pattern>/</url-pattern>

/不覆盖任何其他的servlet。对于所有与其他已注册servlet不匹配的请求,它仅替换servlet容器的内置默认servlet。通常仅在静态资源(CSS / JS / image / etc)和目录列表上调用此方法。servlet容器的内置默认servlet也能够处理HTTP缓存请求,媒体(音频/视频)流和文件下载恢复。通常,您不希望覆盖默认的servlet,否则您将不得不处理它的所有任务,这并不是一件容易的事(JSF实用程序库OmniFaces有一个开放源代码 示例)。因此,这也是servlet的错误URL模式。至于为什么JSP页面没有命中该servlet,这是因为将调用servlet容器的内置JSP servlet,默认情况下已将其映射到更特定的URL模式上*.jsp

<url-pattern></url-pattern>

然后还有一个空字符串URL模式 。请求上下文根时将调用此方法。这与<welcome-file>请求任何子文件夹时不调用它的方法不同。如果您想使用“主页servlet ”,。我只需要承认我会凭直觉期望空字符串URL模式 和斜杠URL模式/完全定义,因此我可以理解,很多入门者对此感到困惑。但是它就是这样啊。

前控制器

如果你确实打算有一个前控制器servlet,那么你最好映射它像一个更具体的网址模式*.html*.do/pages/*/app/*,等你可以藏起来在一个共同的URL模式前端控制器URL模式和覆盖静态资源喜欢/resources/*/static/*等了Servlet过滤器的帮助。另请参阅如何防止映射到/ *的前端控制器servlet处理静态资源。应当注意的是,Spring MVC具有内置的静态资源servlet,因此,/如果在Spring中为静态资源配置通用URL模式,则可以映射其前端控制器。另请参见如何在Spring MVC中处理静态内容?


9
谢谢。经过研究,我想澄清一个细微的问题。/覆盖Web服务器安装的默认servlet。例如,Tomcat安装了一个提供静态资源的DefaultServlet。使用/摆脱默认servlet的副作用(很可能是不希望的)。
赵楚瑜2010年

好吧,我不会称其为“覆盖”,而是“替换”。这样替换默认的servlet可能很有用。
BalusC,2010年

1
<url-pattern> </ url-pattern>引发错误:servlet映射中无效的<url-pattern>
2016年

错误消息来自tomcat,而不是我的IDE;但是,我使用的是Tomcat 6,所以可能是问题所在;)
2016年

2
@BalusC,能否请您告诉我什么/**模式表示?
萨吉布·阿查里亚

45

我想用映射规则和示例来补充BalusC的答案。

Servlet 2.5规范中的映射规则:

  1. 地图确切网址
  2. 映射通配符路径
  3. 地图扩展
  4. 映射到默认servlet

在我们的示例中,有三个servlet。/是我们安装的默认servlet。Tomcat安装了两个servlet来服务jsp和jspx。所以要映射http://host:port/context/hello

  1. 接下来,未安装确切的URL servlet。
  2. 接下来,没有安装通配符路径servlet。
  3. 下一个与任何扩展名都不匹配。
  4. 映射到默认servlet,返回。

到地图 http://host:port/context/hello.jsp

  1. 接下来,未安装确切的URL servlet。
  2. 接下来,没有安装通配符路径servlet。
  3. 找到扩展servlet,返回。

25

也许您还需要知道url的映射方式,因为我经历404了好几个小时。有两种处理请求的处理程序。BeanNameUrlHandlerMappingSimpleUrlHandlerMapping。当定义a时servlet-mapping,我们正在使用SimpleUrlHandlerMapping。我们需要知道的一件事是,这两个处理程序共享一个通用属性alwaysUseFullPath,默认为false

false这意味着Spring将不会使用完整路径将URL映射到控制器。这是什么意思?这意味着当您定义一个servlet-mapping

<servlet-mapping>
    <servlet-name>viewServlet</servlet-name>
    <url-pattern>/perfix/*</url-pattern>
</servlet-mapping>

处理程序实际上将使用*零件来查找控制器。例如,404当您使用以下控制器请求以下控制器时,它将遇到错误/perfix/api/feature/doSomething

@Controller()
@RequestMapping("/perfix/api/feature")
public class MyController {
    @RequestMapping(value = "/doSomething", method = RequestMethod.GET) 
    @ResponseBody
    public String doSomething(HttpServletRequest request) {
        ....
    }
}

这是绝配,对不对?但是为什么呢404。如前所述,默认值of alwaysUseFullPath为false,这意味着在您的请求中,该值仅/api/feature/doSomething用于查找相应的Controller,但没有Controller关心该路径。您需要将URL更改为MyController base /perfix/perfix/api/feature/doSomethingperfix从MyController base中删除@RequestingMapping


8

我认为Candy的答案基本上是正确的。我认为只有一小部分。

要映射主机:port / context / hello.jsp

  1. 接下来,未安装确切的URL servlet。
  2. 找到通配符路径servlet,返回。

我相信为什么“ / *”与host:port / context / hello不匹配,因为它将“ / hello”视为路径而不是文件(因为它没有扩展名)。


2

/*和之间的本质区别在于,将在具有扩展名映射的servlet(如)之前选择/具有映射关系的/*servlet *.html,而/仅在考虑了扩展映射后才选择具有映射关系的servlet (并将用于任何不具有扩展名映射的请求。 t不能匹配其他任何东西---这是“默认servlet”)。

特别是,/*始终会在/映射映射。具有任一阻止任何请求到达容器自己的默认servlet。

或者仅将后servlet映射其是完全匹配(等中选择/foo/bar)和那些路径映射长于/*(像/foo/*)。请注意,空字符串映射与上下文根(http://host:port/context/)完全匹配。

请参阅http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html上的 3.1版中提供的Java Servlet规范的第12章。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.