Web.xml - Servlet与Filter的url-pattern

简介: Web.xml - Servlet与Filter的url-pattern

URL-PATTERN语义详解


在web.xml文件中,以下语法用于定义映射。


① 以"/"开头和以"/*"结尾的是用来做路径映射的。


② 以前缀"*."开头的是用来做扩展映射的。


③ "/" 是用来定义default servlet映射的。


④ 剩下的都是用来定义详细映射的。比如: /aa/bb/cc.action


⑤ /direcotry/*.jsp不支持,容器无法判别是路径映射还是扩展映射。【注意】:"/" 的设置将会将当前指定的 servlet 设为web应用的默认servlet,原来web容器的默认servlet将被替换。!!!


/ 和 /* 之间的区别:

 <url-pattern>/</url-pattern>:将servlet定义为容器默认servlet,当没有其他servlet能够处理当前请求时,由该servlet进行处理。
 <url-pattern>/*</url-pattern>:会匹配所有url - 路径型的和后缀型的url(包括/login , *.jsp , *.js 和 *.html 等)

【1】Filter的url-pattern

filter只要匹配成功,都将会加载 ApplicationFilterFactory部分源码如下:

 /**
     * Return <code>true</code> if the context-relative request path
     * matches the requirements of the specified filter mapping;
     * otherwise, return <code>false</code>.
     *
     * @param filterMap Filter mapping being checked
     * @param requestPath Context-relative request path of this request
     */
    private boolean matchFiltersURL(FilterMap filterMap, String requestPath) {
        // Check the specific "*" special URL pattern, which also matches
        // named dispatches
        if (filterMap.getMatchAllUrlPatterns())
            return (true);
        if (requestPath == null)
            return (false);
        // Match on context relative request path
        String[] testPaths = filterMap.getURLPatterns();
        for (int i = 0; i < testPaths.length; i++) {
            if (matchFiltersURL(testPaths[i], requestPath)) {
                return (true);
            }
        }
        // No match
        return (false);
    }
    /**
     * Return <code>true</code> if the context-relative request path
     * matches the requirements of the specified filter mapping;
     * otherwise, return <code>false</code>.
     *
     * @param testPath URL mapping being checked
     * @param requestPath Context-relative request path of this request
     */
    private boolean matchFiltersURL(String testPath, String requestPath) {
        if (testPath == null)
            return (false);
        // Case 1 - Exact Match
        if (testPath.equals(requestPath))
            return (true);
        // Case 2 - Path Match ("/.../*")
        if (testPath.equals("/*"))
            return (true);
        if (testPath.endsWith("/*")) {
            if (testPath.regionMatches(0, requestPath, 0, 
                                       testPath.length() - 2)) {
                if (requestPath.length() == (testPath.length() - 2)) {
                    return (true);
                } else if ('/' == requestPath.charAt(testPath.length() - 2)) {
                    return (true);
                }
            }
            return (false);
        }
        // Case 3 - Extension Match
        if (testPath.startsWith("*.")) {
            int slash = requestPath.lastIndexOf('/');
            int period = requestPath.lastIndexOf('.');
            if ((slash >= 0) && (period > slash) 
                && (period != requestPath.length() - 1)
                && ((requestPath.length() - period) 
                    == (testPath.length() - 1))) {
                return (testPath.regionMatches(2, requestPath, period + 1,
                                               testPath.length() - 2));
            }
        }
        // Case 4 - "Default" Match
        return (false); // NOTE - Not relevant for selecting filters
    }


三种正确的匹配方式:

emp可替换为替他变量或者字符串。*.do可换其他,如*.jsp

<url-pattern>/*</url-pattern>
<url-pattern>*.do</url-pattern>
<url-pattern>/emp/*</url-pattern>
第二种为扩展名映射,其他两种为路径映射。特定功能的filter可使用具体路径匹配。


两种错误的filter匹配方式:

<url-pattern>/</url-pattern> // 一定不可设置成该方式!
<url-pattern>/emp/</url-pattern>

使用错误的匹配方式,提交form表单,method为post:


【2】Serlvet的url-pattern


servlet只会加载一个匹配成功的,它的匹配原则就是:找到唯一一个最适合的Servlet!

① 首先精确匹配,如定义了两个Servlet:

Servlet1为/foo.htm,Servlet2是/* ;
请求URL为http://localhost/foo.htm;
那么只有Servlet1匹配成功;

② 如果精确匹配不成功,那么会使用第二个原则"最长路径匹配":

如Servlet1为/foo/*,Servlet2为/* ;
请求的URL为:http://localhost/foo/foo.htm;
那么Servlet1匹配成功;

③ 最后根据后缀进行匹配;

④ 如果有default servlet, 那么将会使用默认的servlet进行处理。

即优先级为:

精确匹配>路径匹配>后缀匹配(扩展匹配)>default servlet


如果前面三条规则都没有找到一个servlet,容器会根据url选择对应的请求资源。如果应用定义了一个default servlet,则容器会将请求丢给default servlet。


【几种正确的servlet匹配方式:】

/ --servlet将会替代容器内建的servlet成为default-servlet;

/* --路径映射;

/emp/* --更具体的路径映射;

*.do --扩展名映射。

这里需要说明servlet配置/ 与 /*时的注意事项。


原贴位置如下:

http://stackoverflow.com/questions/4140448/difference-between-and-in-servlet-mapping-url-pattern


当某个servlet的url-pattern设置为"/*"时:

The /* on a servlet overrides all other servlets, 
including all servlets provided by the servletcontainer such as the default servlet and the JSP servlet.
Whatever request you fire, it will end up in that servlet. 
This is thus a bad URL pattern for servlets.
Usually, you'd like to use /* on a Filter only. 
It is able to let the request continue to any of the servlets 
listening on a more specific URL pattern by calling FilterChain#doFilter().

/* 配置的servlet将会比其他所有的(包括容器内建的)servlet具有更高的优先级,那么所有的请求都会在这个servlet结束 !!!

这是非常糟糕的!通常,你更喜欢只在filter中使用 /*。它将通过调用doFilter()方法使请求继续。

当某个servlet的url-pattern设置为"/"时:

The / doesn't override any other servlet. 
It only replaces the servletcontainer's builtin default servlet for all requests which doesn't match any other registered servlet. 
This is normally only invoked on static resources (CSS/JS/image/etc) and directory listings. 
The servletcontainer's builtin default servlet is also capable of dealing with HTTP cache requests,
media (audio/video) streaming and file download resumes.
Usually, you don't want to override the default servlet as you would otherwise have to take care of all its tasks, 
which is not exactly trivial (JSF utility library OmniFaces has an open source example). 
/*下面的说法我并不赞同*/
This is thus also a bad URL pattern for servlets.
As to why JSP pages doesn't hit this servlet, it's because the servletcontainer's builtin JSP servlet will be invoked, 
which is already by default mapped on the more specific URL pattern *.jsp.

解释如下:

这种形式不会覆盖任何其它的servlet,它仅仅替换了servlet容器中内建的默认servlet。


这种形式通常只用来请求静态资源(CSS/JS/image等)和展示目录的列表。


servlet容器内建的默认servlet同样可以处理HTTP cache请求、媒体(声音/视频)流以及文件的下载。


通常来说,你不会想要覆盖这个默认的servlet,否则,你将不得不自己处理一些琐碎的任务。


因此,对于sevlet来说,这同样是一个糟糕的URL模式。


说到为什么JSP页面的请求并不会命中这个servlet,那是因为servlet容器内建的JSP servlet(不是default-servlet)将会被调用,而这个容器内建的JSP servlet已经默认地映射在了*.jsp上。<url-pattern></url-pattern>

  • 如果为空呢?
Then there's also the empty string URL pattern . 
This will be invoked when the context root is requested. 
This is different from the <welcome-file> approach that it isn't invoked when any subfolder is requested.
This is most likely the URL pattern you're actually looking for in case you want a "home page servlet". 
I only have to admit that I'd intuitively expect the empty string URL pattern  
and the slash URL pattern / be defined exactly the other way round, 
so I can understand that a lot of starters got confused on this. 
But it is what it is.


这种空串的形式。当上下文的根被请求的时候,它将被调用。


这与<welcome-file>的方式是不同的,因为这种形式在当任何子目录被请求的时候不会被调用。

当你期望一个“首页servlet”的时候,这种URL模式就是适合你的。


【可能由于环境原因,测试空的url-pattern失败 !】

目录
相关文章
|
5月前
|
Java 数据库连接 容器
8:Servlet生命周期-Java Web
8:Servlet生命周期-Java Web
28 0
|
5月前
|
缓存 安全 Java
7:Servlet表单-Java Web
7:Servlet表单-Java Web
34 0
|
2月前
Could not open ServletContext resource [/WEB-INF/springmvc-servlet.xml]【解决方案】
Could not open ServletContext resource [/WEB-INF/springmvc-servlet.xml]【解决方案】
16 0
|
6天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
2月前
|
Java 应用服务中间件
解决tomcat启动报错:无法在web.xml或使用此应用程序部署的jar文件中解析绝对的url [http:java.sun.com/jsp/jstl/core]
解决tomcat启动报错:无法在web.xml或使用此应用程序部署的jar文件中解析绝对的url [http:java.sun.com/jsp/jstl/core]
154 1
|
2月前
|
Java 数据处理 数据库
Java Web开发中的Servlet
Java Web开发中的Servlet
|
3月前
|
Java 应用服务中间件 API
深入解析Java Servlet技术在Web开发中的应用
深入解析Java Servlet技术在Web开发中的应用
214 1
|
4月前
|
前端开发 JavaScript Java
基于servlet+jsp+mysql实现的java web校园车辆管理系统
基于servlet+jsp+mysql实现的java web校园车辆管理系统
|
4月前
|
XML 前端开发 Java
Web开发: 什么是Servlet和JSP?
Web开发: 什么是Servlet和JSP?
82 0
|
5月前
|
Java 编译器 应用服务中间件
5:Servlet程序-Java Web
5:Servlet程序-Java Web
15 1