Servlets servlet映射url模式中/和/*之间的差异

Servlets servlet映射url模式中/和/*之间的差异,servlets,web.xml,url-pattern,Servlets,Web.xml,Url Pattern,熟悉的代码: 主要的 /* 主要的 / 我的理解是/*映射到http://host:port/context/* 怎么样?它肯定不会映射到http://host:port/context 只有根。事实上,它会接受的http://host:port/context/hello,但拒绝http://host:port/context/hello.jsp. 有人能解释一下这是怎么回事吗http://host:port/context/hello 地图/* servlet上的/*覆盖所有其他servle

熟悉的代码:

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

怎么样?它肯定不会映射到http://host:port/context 只有根。事实上,它会接受的http://host:port/context/hello,但拒绝http://host:port/context/hello.jsp.

有人能解释一下这是怎么回事吗http://host:port/context/hello 地图

/* servlet上的/*覆盖所有其他servlet,包括servlet容器提供的所有servlet,如默认servlet和JSP servlet。无论您发出什么请求,它都将在该servlet中结束。因此,对于servlet来说,这是一个糟糕的URL模式。通常情况下,您只希望在服务器上使用/*。通过调用,它可以让请求继续发送到任何侦听更特定URL模式的servlet

/ /不会覆盖任何其他servlet。对于所有与任何其他已注册servlet不匹配的请求,它只替换servletcontainer的内置默认servlet。这通常仅在静态资源CSS/JS/image/etc和目录列表上调用。servletcontainer的内置默认servlet还能够处理HTTP缓存请求、媒体音频/视频流和文件下载恢复。通常,您不希望覆盖默认servlet,否则您将不得不处理它的所有任务,而JSF实用程序库并没有一个简单的功能。因此,对于servlet来说,这也是一种糟糕的URL模式。至于JSP页面为什么没有命中这个servlet,这是因为servletcontainer的内置JSP servlet将被调用,默认情况下,它已经映射到更具体的URL模式*.JSP上

然后还有空字符串URL模式。当请求上下文根目录时,将调用它。这与请求任何子文件夹时不调用它的方法不同。这很可能是您实际寻找的URL模式,以防您需要一个URL。我只需要承认,我直觉上认为空字符串URL模式和斜杠URL模式/的定义正好相反,所以我可以理解很多初学者对此感到困惑。但事实就是这样

前端控制器
如果您确实打算使用前端控制器servlet,那么最好将其映射到更具体的URL模式,如*.html、*.do、/pages/*、/app/*,等等。您可以隐藏前端控制器URL模式,并在servlet过滤器的帮助下在公共URL模式(如/resources/*、/static/*等)上覆盖静态资源。另见。应该注意的是,SpringMVC有一个内置的静态资源servlet,因此,如果您在Spring中为静态资源配置一个公共URL模式,那么就可以在上映射它的前端控制器。另请参见

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

Servlet 2.5规范中的映射规则:

映射精确的URL 映射通配符路径 地图扩展 映射到默认servlet 在我们的示例中,有三个servlet是我们安装的默认servlet。Tomcat安装了两个servlet来服务jsp和jspx。因此,我们需要绘制地图http://host:port/context/hello

未安装准确的URL servlet,下一步。 未安装通配符路径servlet,下一步。 不匹配任何扩展名,下一个。 映射到默认servlet,返回。 绘制http://host:port/context/hello.jsp

未安装准确的URL servlet,下一步。 未安装通配符路径servlet,下一步。 找到扩展servlet,返回。
我认为坎蒂的回答基本上是正确的。有一小部分我不这么认为

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

未安装准确的URL servlet,下一步。 找到通配符路径servlet,返回。
我认为why/*与host:port/context/hello不匹配,因为它将/hello视为路径而不是文件,因为它没有扩展名。

也许您也需要知道URL是如何映射的,因为我经历了数小时的404。有两种处理程序处理请求。BeanNameUrlHandlerMapping和SimpleUrlHandlerMapping。当我们定义servlet映射时,我们使用的是SimpleUrlHandlerMapping。我们需要知道的一件事是,这两个处理程序共享一个名为AlwaySuselflPath的公共属性,该属性默认为false

false在这里表示Spring不会使用完整路径将url映射到控制器。这是什么意思?这意味着定义servlet映射时:


这是一场完美的比赛,对吗?但为什么是404。如前所述,AlwaySuseFillPath的默认值为false,这意味着在您的请求中,只有/api/feature/doSomething用于查找相应的控制器,但没有控制器关心该路径。您需要将url更改为/perfix/perfix/api/feature/doSomething,或者从MyController base@RequestingMapping中删除perfix

/*和/之间的本质区别在于,将在任何具有扩展映射(如*.html,w)的servlet之前选择具有映射/*的servlet 只有在考虑了扩展映射之后,才会选择带有mapping/的servlet,并将其用于任何与其他内容不匹配的请求——它是默认的servlet

特别是,始终在a/mapping之前选择a/*映射。使用其中一个可以防止任何请求到达容器自己的默认servlet

只有在servlet映射(与/foo/bar等完全匹配)和路径映射(与/foo/*等路径映射长度相同)之后,才会选择其中一个。请注意,空字符串映射与上下文根完全匹配http://host:port/context/.


请参阅Java Servlet规范第12章,该规范在3.1版中提供。

谢谢。经过一些研究,我想澄清一个微妙的问题覆盖web服务器安装的默认servlet。例如,Tomcat安装了一个为静态资源服务的DefaultServlet。使用/摆脱默认servlet很可能是一个不受欢迎的副作用。我不认为它是覆盖,而是替换。这样替换默认servlet可能会很有用。抛出错误:在servlet中无效mapping@BalusC,你能告诉我/**模式表示什么吗?我相信这个答案是错误的。/*不会覆盖所有其他servlet,并且不是所有请求都会在那里结束。容器将首先尝试查找精确匹配,然后查找最长路径前缀匹配。因此,带有mapping/foo/bar的servlet或带有mapping/foo/*的servlet将在带有mapping/*的servlet之前启动。但是,带有/*的将覆盖任何扩展映射,如*.html。
<servlet-mapping>
    <servlet-name>viewServlet</servlet-name>
    <url-pattern>/perfix/*</url-pattern>
</servlet-mapping>
@Controller()
@RequestMapping("/perfix/api/feature")
public class MyController {
    @RequestMapping(value = "/doSomething", method = RequestMethod.GET) 
    @ResponseBody
    public String doSomething(HttpServletRequest request) {
        ....
    }
}