servlet的url-pattern匹配规则

1. 说明

(1)servlet容器中url-pattern匹配规则不是简单的字符串匹配,也不是正则表达式匹配,而是通过特定的规则进行匹配(匹配优先级、完全匹配、长路径匹配优先、特殊默认匹配等规则)

(2)servlet2.5开始,一个servlet可以有多个url-pattern规则。

(3)参与路径匹配的是容器收到的请求去掉当前应用上下文后字符串。如收到的url请求时http://localhost:8080/sa-admin/user/getUserList,其应用名称是sa-admin,应用的上下文路径是http://localhost:8080/sa-admin,故用来做serlvet映射匹配的字符串是:/user/getUserList(注意,前面带有/)。

(4)当有一个servlet匹配成功后,其他的servlet不会再处理请求。

2. 匹配规则

2.1 精准匹配

url-pattern中的配置,必须与url完全精准匹配

完全精准匹配,指的是字符串必须完全一样。如映射路径为/user/userAdd,则请求url为/user/userAdd/,后面多一个/是无法完全精准匹配到servlet的。

如:

/user/userAdd
2.2 路径匹配

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

先最长路径匹配,再最短路径匹配。

如:

/user/*
/*
2.3 扩展名匹配

以"*."开头的匹配路径

如:

*.action
*.jpg
*.jsp
2.4 缺省匹配

固定路径"/",当前所有的匹配规则都无法匹配到路径时,会执行缺省匹配对应的servlet

3. 匹配顺序(重要)

精准匹配 > 路径匹配 > 扩展名匹配 > 缺省匹配

4. 注意问题
4.1 “路径匹配”和“扩展名匹配”不可同时设置。

正确的设置只能是如下,其他的均为非法,而且如果合法,出现在非指定位置的"*",会作为普通字符串处理:

(1)精确匹配

(2)以"/“开头,以"/*结尾”

(3)以"*."开头

/user/*.action是非法的。
/user/*/userAdd是精确匹配,合法,此处的*代表的是字符串中的"*",而不是通配符。
4.2 "/*“和”/"含义的区别
  • "/*"属于路径匹配(长度最短),优先级仅仅低于精准匹配和长字符串的路径匹配,也即,如果未为路径配置精准匹配,或者未配置符合路径规则的长路径匹配(如/user/*之类的符合条件的路径匹配),则请求一定会被匹配到此路径。

  • "/"是servlet中特殊的匹配模式,优先级最低,所有配置的路径均无法匹配到路径时,会匹配到此特殊路径。该模式有且只有一个实例,默认web容器中均会设置一个默认的servlet来实现此特殊匹配。如tomcat的conf/web.xml文件中就进行了此配置,如下:

    <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-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

    部署在tomcat容器中的自定义应用,可以在web.xml中自定义servlet的url-pattern,自定义后将覆盖容器中的默认servlet,如下:

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

    容器中的default默认servlet将不再起作用(其他容器servlet如jsp,仍然起作用)。

    	容器中的默认default有映射webapp目录下静态资源到页面的功能,也就是如果自定义应用的webapp目录下有个top.jpg文件,应用上下文为http://localhost:8080/sa-admin,则可以通过http://localhost:8080/sa-admin/top.jpg访问此文件。
    
    	因此,如在自定义应用中定义了servlet的url-pattern为"/"(springMvc定义DispatcherServlet的传统配置),将无法通过路径访问系统webapp目录下的静态资源,将返回404错误。故springMvc中可通过如下标签,来实现静态资源的访问:
    
    <mvc:default-servlet-handler/>
    

    该标签说明如下:

    Configures a handler for serving static resources by forwarding to the Servlet container's default Servlet.
    Use of this handler allows using a “/” mapping with the DispatcherServlet while still utilizing the Servlet
    container to serve static resources.
    This handler will forward all requests to the default Servlet. Therefore it is important that it remains last
    in the order of all other URL HandlerMappings. That will be the case if you use the “annotation-driven” element
    or alternatively if you are setting up your customized HandlerMapping instance be sure to set its “order”
    property to a value lower than that of the DefaultServletHttpRequestHandler, which is Integer.MAX_VALUE.

    注意,此标签作用,为将静态资源,转发到Servlet容器的默认Servlet(tomcat容器中为default)。对应源码如下:

    文件DefaultServletHttpRequestHandler:

    public class DefaultServletHttpRequestHandler implements HttpRequestHandler, ServletContextAware {
    
    	/** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish */
    	private static final String COMMON_DEFAULT_SERVLET_NAME = "default";
    
    	/** Default Servlet name used by Google App Engine */
    	private static final String GAE_DEFAULT_SERVLET_NAME = "_ah_default";
    
    	/** Default Servlet name used by Resin */
    	private static final String RESIN_DEFAULT_SERVLET_NAME = "resin-file";
    
    	/** Default Servlet name used by WebLogic */
    	private static final String WEBLOGIC_DEFAULT_SERVLET_NAME = "FileServlet";
    
    	/** Default Servlet name used by WebSphere */
    	private static final String WEBSPHERE_DEFAULT_SERVLET_NAME = "SimpleFileServlet";
        
        ......
            
    	@Override
    	public void handleRequest(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    
    		RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName);
    		if (rd == null) {
    			throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" +
    					this.defaultServletName + "'");
    		}
    		rd.forward(request, response);
    	}
    
    
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值