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

目录
相关文章
|
26天前
|
Java 应用服务中间件 Spring
【终极解决方案】Could not open ServletContext resource [/WEB-INF/dispatcher-servlet.xml]
【终极解决方案】Could not open ServletContext resource [/WEB-INF/dispatcher-servlet.xml]
20 0
|
3月前
|
存储 缓存 前端开发
Servlet与JSP在Java Web应用中的性能调优策略
Servlet与JSP在Java Web应用中的性能调优策略
31 1
|
3月前
|
XML Android开发 UED
"掌握安卓开发新境界:深度解析AndroidManifest.xml中的Intent-filter配置,让你的App轻松响应scheme_url,开启无限交互可能!"
【8月更文挑战第2天】在安卓开发中,scheme_url 通过在`AndroidManifest.xml`中配置`Intent-filter`,使应用能响应特定URL启动或执行操作。基本配置下,应用可通过定义特定URL模式的`Intent-filter`响应相应链接。
108 12
|
3月前
|
C# 数据可视化 开发者
WPF开发者福音:深度解析OxyPlot与LiveCharts图表库,轻松实现数据可视化不再是难题!
【8月更文挑战第31天】在WPF应用中,数据可视化对提升用户体验至关重要。本文介绍并演示了两种流行图表库OxyPlot和LiveCharts的集成与使用方法。OxyPlot是一款适用于.NET应用的开源图表库,提供多种图表类型,易于集成。LiveCharts则以其丰富的图表类型和动画效果,特别适合实时数据展示。通过具体代码示例,本文展示了如何利用这两种图表库创建折线图和柱状图,并详细说明了安装和配置步骤。希望本文能帮助开发者在WPF应用中轻松实现高效、美观的数据可视化。
159 0
|
3月前
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
基于Servlet和JSP的Java Web应用开发指南
38 0
|
3月前
|
监控 前端开发 Java
揭秘Web开发神器:Servlet、过滤器、拦截器、监听器如何联手打造无敌博客系统,让你的用户欲罢不能!
【8月更文挑战第24天】在Java Web开发中,Servlet、过滤器(Filter)、拦截器(Interceptor,特指Spring MVC中的)及监听器(Listener)协同工作,实现复杂应用逻辑。以博客系统为例,Servlet处理文章详情请求,过滤器(如LoginFilter)检查登录状态并重定向,Spring MVC拦截器(如LoggingInterceptor)提供细粒度控制(如日志记录),监听器(如SessionListener)监控会话生命周期事件。这些组件共同构建出高效、有序的Web应用程序。
36 0
|
4月前
|
开发框架 JSON 前端开发
利用过滤器Filter和特性Attribute实现对Web API返回结果的封装和统一异常处理
利用过滤器Filter和特性Attribute实现对Web API返回结果的封装和统一异常处理
|
4月前
|
搜索推荐 UED Python
动态多条件查询:理解`filter_by`与`filter`提升Web应用搜索功能
通过深入理解filter_by与filter的异同,并结合使用它们,我们可以构建一个既灵活又强大的动态多条件查询系统。这不仅提升了Web应用的搜索功能,也为用户提供了更加个性化的搜索体验。希望本文能够启发你在自己项目中实现类似的功能,以满足用户多变的搜索需求。
|
5月前
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
【6月更文挑战第23天】构建Java Web应用,Servlet与JSP携手打造在线图书管理系统,涵盖需求分析、设计、编码到测试。通过实例展示了Servlet如何处理用户登录(如`LoginServlet`),JSP负责页面展示(如`login.jsp`和`bookList.jsp`)。应用基于MySQL数据库,包含用户和图书表。登录失败显示错误信息,成功后展示图书列表。部署到Tomcat服务器测试功能。此基础教程为深入Java Web开发奠定了基础。
99 10
|
4月前
|
搜索推荐 UED Python
动态多条件查询:理解`filter_by`与`filter`提升Web应用搜索功能
了解SQLAlchemy中`filter_by`与`filter`对提升Web应用搜索功能至关重要。`filter_by`简化了等值查询,而`filter`则支持复杂的表达式和逻辑组合。通过动态获取用户输入,构建基础查询并根据条件应用过滤,可以创建灵活的搜索系统。结合分页和排序,为用户提供定制化搜索体验。掌握这两者,能增强应用的交互性和实用性。
76 0
动态多条件查询:理解`filter_by`与`filter`提升Web应用搜索功能