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

熟悉的代码:

<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映射?

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

servlet上的/*覆盖所有其他的servlet,包括servlet容器提供的所有servlet,比如默认的servlet和JSP servlet。 不pipe你发起什么请求,它都会在这个servlet中结束。 这是servlet的一个错误的URL模式。 通常,您只想在Filter上使用/* 。 通过调用FilterChain#doFilter()它可以让请求继续到监听更具体的URL模式的任何servlet。

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

/不会覆盖任何其他的servlet。 它只replaceservletcontainer的内置默认servlet,用于所有不匹配任何其他注册servlet的请求。 这通常只在静态资源(CSS / JS / image / etc)和目录列表上被调用。 servlet容器的内置默认servlet也能够处理HTTPcaching请求,媒体(audio/video)stream和文件下载恢复。 通常,您不希望覆盖默认的servlet,否则您将不得不处理所有的任务,这并不是很重要(JSF实用程序库OmniFaces有一个开源 示例 )。 这也是servlet的一个错误的URL模式。 至于为什么JSP页面没有命中这个servlet,这是因为servlet容器内置的JSP servlet将被调用,这已经默认映射到更具体的URL模式*.jsp

<url-pattern></url-pattern>

然后还有空string的URL模式 。 这将在请求上下文根时被调用。 这与<welcome-file>方法不同,它在请求任何子文件夹时不会被调用。 如果您想要“ 主页servlet ”,这很可能是您实际寻找的URL模式。 我只需要承认,我会直观地期望空string的URL模式 和斜杠URL模式/正好相反,所以我可以理解,很多初学者对此感到困惑。 但它是这样的。

前部控制器

如果你真的打算有一个前端控制器的servlet,那么你最好把它映射到一个更具体的URL模式,如*.html*.do/pages/*/app/*等。你可以隐藏前端控制器的URL模式,并在servletfilter的帮助下,覆盖像/resources/*/static/*等通用URL模式的静态资源。 另请参见如何防止静态资源被映射在/ *上的前端控制器servlet处理 。 值得注意的是,Spring MVC有一个内置的静态资源servlet,所以这就是为什么你可以将它的前端控制器映射到/如果你在Spring中为静态资源configuration了一个通用的URL模式。 另请参见如何处理Spring MVC中的静态内容?

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

从Servlet 2.5规范映射规则:

  1. 地图确切的url
  2. 映射通配符path
  3. 地图扩展
  4. 映射到默认的servlet

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

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

映射http://host:port/context/hello.jsp

  1. 没有安装确切的URL servlet,接下来。
  2. 接下来没有安装通配符path的servlet。
  3. find扩展servlet,返回。

也许你需要知道如何映射url,因为我已经404几个小时了。 有两种处理请求的处理程序。 BeanNameUrlHandlerMappingSimpleUrlHandlerMapping 。 当我们定义一个servlet-mapping ,我们使用SimpleUrlHandlerMapping 。 我们需要知道的一件事是这两个处理程序共享一个名为alwaysUseFullPath的公共属性,默认为false

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

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

处理程序将实际使用*部分来查找控制器。 例如,当您使用/perfix/api/feature/doSomething请求时,以下控制器将面临404错误

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

这是一个完美的搭配,对吧? 但为什么404 。 如前所述, alwaysUseFullPath默认值为false,这意味着在您的请求中,只有/api/feature/doSomething用于查找相应的Controller,但Controller没有关心该path。 你需要改变你的url/perfix/perfix/api/feature/doSomething或从MyController base @RequestingMapping删除perfix

我认为糖果的答案大多是正确的。 有一小部分,我认为不然。

要映射主机:端口/上下文/ hello.jsp

  1. 没有安装确切的URL servlet,接下来。
  2. find通配符path的servlets ,返回。

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

/*/之间的本质区别是,在任何带有扩展映射的servlet(比如*.html )之前,将会select一个映射为/* servlet,而只有在考虑到扩展映射之后才会select映射为/的servlet将被用于任何不匹配其他任何请求—它是“默认的servlet”)。

特别是, /*映射将始终在映射之前被选中。 防止任何请求到达容器自己的默认servlet。

只有在完全匹配的servlet映射(如/foo/bar )和path映射比/* (如/foo/* )更长的映射之后才会被选中。 请注意,空string映射与上下文根( http://host:port/context/ )完全匹配。

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