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失败 !】

目录
相关文章
|
安全 PHP 开发者
Web安全-URL跳转与钓鱼
Web安全-URL跳转与钓鱼
592 8
|
XML Android开发 UED
"掌握安卓开发新境界:深度解析AndroidManifest.xml中的Intent-filter配置,让你的App轻松响应scheme_url,开启无限交互可能!"
【8月更文挑战第2天】在安卓开发中,scheme_url 通过在`AndroidManifest.xml`中配置`Intent-filter`,使应用能响应特定URL启动或执行操作。基本配置下,应用可通过定义特定URL模式的`Intent-filter`响应相应链接。
571 12
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
基于Servlet和JSP的Java Web应用开发指南
683 1
|
存储 缓存 前端开发
Servlet与JSP在Java Web应用中的性能调优策略
Servlet与JSP在Java Web应用中的性能调优策略
326 1
|
自然语言处理 前端开发 Java
Servlet与JSP:Java Web开发的基石技术详解
【6月更文挑战第23天】Java Web的Servlet与JSP是动态网页的核心。Servlet是服务器端的Java应用,处理HTTP请求并响应;JSP则是结合HTML与Java代码的页面,用于动态内容生成。Servlet通过生命周期方法如`init()`、`service()`和`destroy()`工作,而JSP在执行时编译成Servlet。两者在MVC架构中分工,Servlet处理逻辑,JSP展示数据。尽管有Spring MVC等框架,Servlet和JSP仍是理解Web开发基础的关键。
489 12
|
Java 应用服务中间件 Spring
【终极解决方案】Could not open ServletContext resource [/WEB-INF/dispatcher-servlet.xml]
【终极解决方案】Could not open ServletContext resource [/WEB-INF/dispatcher-servlet.xml]
463 0
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
【6月更文挑战第23天】构建Java Web应用,Servlet与JSP携手打造在线图书管理系统,涵盖需求分析、设计、编码到测试。通过实例展示了Servlet如何处理用户登录(如`LoginServlet`),JSP负责页面展示(如`login.jsp`和`bookList.jsp`)。应用基于MySQL数据库,包含用户和图书表。登录失败显示错误信息,成功后展示图书列表。部署到Tomcat服务器测试功能。此基础教程为深入Java Web开发奠定了基础。
492 10
|
缓存 负载均衡 安全
Servlet与JSP在Java Web应用中的性能调优策略
【6月更文挑战第23天】在Java Web中,Servlet和JSP调优至关重要,以应对高并发和复杂业务带来的性能挑战。优化包括Servlet复用、线程安全、数据库连接池,以及JSP的编译优化、使用JSTL、页面缓存和静态内容分离。全局优化涉及负载均衡、异步处理和缓存策略。通过这些实践,开发者能提升应用响应速度和吞吐量,确保高负载下的稳定运行。
490 7
|
搜索推荐 Java 数据库连接
探索Java Web开发:Servlet与JSP的协同工作原理
【6月更文挑战第23天】Java Web开发中,Servlet和JSP协同打造动态网站。Servlet是服务器端的Java程序,处理HTTP请求并执行复杂逻辑;JSP则结合HTML和Java,生成动态内容。Servlet通过`doGet()`等方法响应请求,JSP在首次请求时编译成Servlet。两者常搭配使用,Servlet处理业务,JSP专注展示,通过`RequestDispatcher`转发实现数据渲染。这种组合是Java Web应用的基础,即使新技术涌现,其价值仍然重要,为开发者提供了强大的工具集。
409 7
|
XML 数据格式
XML配置Servlet文件,不使用注解配置路径的方法
XML配置Servlet文件,不使用注解配置路径的方法