zoukankan      html  css  js  c++  java
  • java-servlet的url-pattern匹配规则详细描述

    http://www.cnblogs.com/51kata/p/5152400.html

    http://www.cnblogs.com/canger/p/6084846.html

    一、概述

    在利用servlet或Filter进行url请求的匹配时,很关键的一点就是匹配规则,但servlet容器中的匹配规则既不是简单的通配,也不是正则表达式,而是由自己的规则,比较容易混淆。本文来详细举例介绍下。下面的说明都是在tomcat服务器中得到验证的。

    先介绍一下匹配的概念,上例子代码。在一个app(如名字为myapp)的web.xml文件中,有如下信息:

    复制代码
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.nau.MyServlet</servlet-class>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>xxxxxx</url-pattern>
       <url-pattern>yyyyyyy</url-pattern>
      </servlet-mapping>
    复制代码

    上面的配置信息,其中<servlet>标签首先配置声明一个servlet,包括servlet的名字和对应的java类名。
    其中<servlet-mapping>标签声明了与该servlet相应的匹配规则,每个<url-pattern>标签代表1个匹配规则。

    当浏览器发起一个url请求后,该请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如url是http://10.43.11.143/myapp/kata/detail.html,其应用上下文是myapp,容器会将http://10.43.11.143/myapp去掉,剩下的/kata/detail.html部分拿来做servlet的映射匹配。这个映射匹配过程是有优先顺序的(具体的优先顺序规则后面介绍),而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了。

    注意Filter的匹配规则与servlet一样,但对于filter,不会像servlet那样只匹配一个servlet,因为filter的集合是一个链,所以只会有处理的顺序不同,而不会出现只选择一个filter。Filter的处理顺序和filter-mapping在web.xml中定义的顺序相同。 

    下面我们详细介绍各种匹配规则

    二、精确匹配

    <url-pattern>中配置的项必须与url完全精确匹配。

    如配置信息如下:

    复制代码
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/kata/detail.html</url-pattern>
        <url-pattern>/demo.html</url-pattern>
        <url-pattern>/table</url-pattern>
    </servlet-mapping>
    复制代码

    当在浏览器中输入如下几种url时,都会被匹配到该servlet
    http://10.43.11.143/myapp/kata/detail.html
    http://10.43.11.143/myapp/demo.html
    http://10.43.11.143/myapp/table

    注意:

    http://10.43.11.143/myapp/table/ 是非法的url,不会被当作http://10.43.11.143/myapp/table识别

    另外上述url后面可以跟任意的查询条件,都会被匹配,如

    http://10.43.11.143/myapp/table?hello 这个请求就会被匹配到MyServlet。

    三、扩展名匹配

    如果匹配规则如下

    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>*.jsp</url-pattern>
    </servlet-mapping>

    则任何扩展名为jsp(文件名和路径任意)的url请求都会匹配,比如下面的url都会被匹配
    http://10.43.11.143/myapp/demo.jsp
    http://10.43.11.143/myapp/test.jsp

    四、路径匹配

    如果匹配规则如下

    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/kata/*</url-pattern>
    </servlet-mapping>

    则请求的ulr只要前面(myapp之后)的路径是/kata,而后面的路径可以任意。比如下面的url都会被匹配。
    http://10.43.11.143/myapp/kata/demo.html
    http://10.43.11.143/myapp/kata/test.jsp
    http://10.43.11.143/myapp/kata/test/detail.html

    http://10.43.11.143/myapp/kata/action

    http://10.43.11.143/myapp/kata/action/

    注意:路径和扩展名匹配无法同时设置,比如下面的三个<url-pattern>都是非法的,如果设置,启动tomcat服务器会报错。

    <url-pattern>/kata/*.jsp</url-pattern>

    <url-pattern>/*.jsp</url-pattern>

    <url-pattern>he*.jsp</url-pattern>

    另外注意:<url-pattern>/aa/*/bb</url-pattern>
    这个是精确匹配,url必须是 /aa/*/bb,这里的*不是通配的含义

    五、匹配任意的url

    如果<url-pattern>配置成如下两种的任意一种

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

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

    则所有的url都可以被匹配上。其中/*是路径匹配,只是路径就是/。

    六、优先顺序

    当一个url与多个servlet的匹配规则可以匹配时,则按照 “ 精确路径 > 最长路径>扩展名”这样的优先级匹配到对应的servlet。举例如下:

    例1:比如servletA 的url-pattern为 /test,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,不会去管servletB。

    例2:比如servletA的url-pattern为/test/*,而servletB的url-pattern为/test/a/*,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB。 

    例3: 比如servletA的url-pattern:*.action ,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test.action,这个时候容器就会优先进行路径匹配,而不是去匹配扩展名,这样就去调用servletB。

    七、小结

    本文我们详细介绍了servlet的匹配规则。总的来说就是分为精确、路径和扩展名三种匹配方式,并且介绍了优先级。

    ===========================

    首先需要明确几容易混淆的规则:

    1. servlet容器中的匹配规则既不是简单的通配,也不是正则表达式,而是特定的规则。所以不要用通配符或者正则表达式的匹配规则来看待servlet的url-pattern。
    2. Servlet 2.5开始,一个servlet可以使用多个url-pattern规则,<servlet-mapping>标签声明了与该servlet相应的匹配规则,每个<url-pattern>标签代表1个匹配规则;
    3. 当servlet容器接收到浏览器发起的一个url请求后,容器会用url减去当前应用的上下文路径,以剩余的字符串作为servlet映射,假如url是http://localhost:8080/appDemo/index.html,其应用上下文是appDemo,容器会将http://localhost:8080/appDemo去掉,用剩下的/index.html部分拿来做servlet的映射匹配
    4. url-pattern映射匹配过程是有优先顺序的
    5. 而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了。

    一、四种匹配规则

    精确匹配

      <url-pattern>中配置的项必须与url完全精确匹配。

    复制代码
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/user/users.html</url-pattern>
        <url-pattern>/index.html</url-pattern>
        <url-pattern>/user/addUser.action</url-pattern>
    </servlet-mapping>
    复制代码

      当在浏览器中输入如下几种url时,都会被匹配到该servlet
      http://localhost:8080/appDemo/user/users.html
      http://localhost:8080/appDemo/index.html
      http://localhost:8080/appDemo/user/addUser.action

      

      注意:

      http://localhost:8080/appDemo/user/addUser/ 是非法的url,不会被当作http://localhost:8080/appDemo/user/addUser识别

      另外上述url后面可以跟任意的查询条件,都会被匹配,如

      http://localhost:8080/appDemo/user/addUser?username=Tom&age=23 会被匹配到MyServlet。

    2 扩展名匹配

      以“*.”开头的字符串被用于扩展名匹配

    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>*.jsp</url-pattern>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

      则任何扩展名为jsp或action的url请求都会匹配,比如下面的url都会被匹配
      http://localhost:8080/appDemo/user/users.jsp
      http://localhost:8080/appDemo/toHome.action

    3 路径匹配

      以“/”字符开头,并以“/*”结尾的字符串用于路径匹配

      

    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/user/*</url-pattern>
    </servlet-mapping>

      路径以/user/开始,后面的路径可以任意。比如下面的url都会被匹配。
      http://localhost:8080/appDemo/user/users.html
      http://localhost:8080/appDemo/user/addUser.action
      http://localhost:8080/appDemo/user/updateUser.actionl

    4 缺省匹配

      

    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    二、匹配顺序

    1. 精确匹配,servlet-mapping1:<url-pattern>/user/users.html</url-pattern>,servlet-mapping2:<url-pattern>/*</url-pattern>。当一个请求http://localhost:8080/appDemo/user/users.html来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配
    2. 路径匹配,先最长路径匹配,再最短路径匹配servlet-mapping1:<url-pattern>/user/*</url-pattern>,servlet-mapping2:<url-pattern>/*</url-pattern>。当一个请求http://localhost:8080/appDemo/user/users.html来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配
    3. 扩展名匹配,servlet-mapping1:<url-pattern>/user/*</url-pattern>,servlet-mapping2:<url-pattern>*.action</url-pattern>。当一个请求http://localhost:8080/appDemo/user/addUser.action来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配
    4. 缺省匹配,以上都找不到servlet,就用默认的servlet,配置为<url-pattern>/</url-pattern>

    三、需要注意的问题

    1 路径匹配和扩展名匹配无法同时设置

      匹配方法只有三种,要么是路径匹配(以“/”字符开头,并以“/*”结尾),要么是扩展名匹配(以“*.”开头),要么是精确匹配,三种匹配方法不能进行组合,不要想当然使用通配符或正则规则。

      如<url-pattern>/user/*.action</url-pattern>是非法的

      另外注意:<url-pattern>/aa/*/bb</url-pattern>是精确匹配,合法,这里的*不是通配的含义

    2 "/*"和"/"含义并不相同

    • “/*”属于路径匹配,并且可以匹配所有request,由于路径匹配的优先级仅次于精确匹配,所以“/*”会覆盖所有的扩展名匹配,很多404错误均由此引起,所以这是一种特别恶劣的匹配模式,一般只用于filter的url-pattern
    • “/”是servlet中特殊的匹配模式,切该模式有且仅有一个实例,优先级最低,不会覆盖其他任何url-pattern,只是会替换servlet容器的内建default servlet ,该模式同样会匹配所有request。
    • 配置“/”后,一种可能的现象是myServlet会拦截诸如http://localhost:8080/appDemo/user/addUser.action、http://localhost:8080/appDemo/user/updateUser的格式的请求,但是并不会拦截http://localhost:8080/appDemo/user/users.jsp、http://localhost:8080/appDemo/index.jsp,这是应为servlet容器有内置的“*.jsp”匹配器,而扩展名匹配的优先级高于缺省匹配,所以才会有上述现象。

      Tomcat在%CATALINA_HOME%confweb.xml文件中配置了默认的Servlet,配置代码如下

      

    复制代码
    <servlet>
            <servlet-name>default</servlet-name>
            <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
            <init-param>
                <param-name>debug</param-name>
                <param-value>0</param-value>
            </init-param>
            <init-param>
                <param-name>listings</param-name>
                <param-value>false</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    <servlet>
            <servlet-name>jsp</servlet-name>
            <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
            <init-param>
                <param-name>fork</param-name>
                <param-value>false</param-value>
            </init-param>
            <init-param>
                <param-name>xpoweredBy</param-name>
                <param-value>false</param-value>
            </init-param>
            <load-on-startup>3</load-on-startup>
     </servlet>
    <servlet-mapping>
            <servlet-name>default</servlet-name>
            <url-pattern>/</url-pattern>
    </servlet-mapping>
    
        <!-- The mappings for the JSP servlet -->
    <servlet-mapping>
            <servlet-name>jsp</servlet-name>
            <url-pattern>*.jsp</url-pattern>
            <url-pattern>*.jspx</url-pattern>
    </servlet-mapping>
    复制代码
    • 可以阅读http://stackoverflow.com/questions/4140448/difference-between-and-in-servlet-mapping-url-pattern
    • “/*”和“/”均会拦截静态资源的加载,需要特别注意

    四、举例

    映射的URL 对应的Servlet
    /hello servlet1
    /bbs/admin/* servlet2
    /bbs/* servlet3
    *.jsp servlet4
    / servlet5

     

     

     

     

     

     

     

    实际请求映射的结果

    去掉上下文路径的剩余路径

    处理请求的Servlet

    /hello

    servlet1

    /bbs/admin/login

    servlet2

    /bbs/admin/index.jsp

    servlet2

    /bbs/display

    servlet3

    /bbs/index.jsp

    servlet3

    /bbs

    servlet3

    /index.jsp

    servler4

    /hello/index.jsp

    servlet4

    /hello/index.html

    servlet5

    /news

    servlet5

  • 相关阅读:
    高精度计算
    高精度除以低精度
    P1258 小车问题
    POJ 2352 stars (树状数组入门经典!!!)
    HDU 3635 Dragon Balls(超级经典的带权并查集!!!新手入门)
    HDU 3938 Portal (离线并查集,此题思路很强!!!,得到所谓的距离很巧妙)
    POJ 1703 Find them, Catch them(确定元素归属集合的并查集)
    HDU Virtual Friends(超级经典的带权并查集)
    HDU 3047 Zjnu Stadium(带权并查集,难想到)
    HDU 3038 How Many Answers Are Wrong(带权并查集,真的很难想到是个并查集!!!)
  • 原文地址:https://www.cnblogs.com/hfultrastrong/p/7239588.html
Copyright © 2011-2022 走看看