Servlet和Filter的url匹配以及url-pattern详解(转)

本文深入解析Servlet和Filter在J2EE开发中的URL匹配过程,详细解释了匹配规则和顺序,并指出容易导致错误的URL配置方式。通过案例分析帮助开发者避免常见问题。

     Servlet和filter是J2EE开发中常用的技术,使用方便,配置简单,老少皆宜。估计大多数朋友都是直接配置用,也没有关心过具体的细节,今天遇到一个问题,上网查了servlet的规范才发现,servlet和filter中的url-pattern还是有一些文章在里面的,总结了一些东西,放出来供大家参考,以免遇到问题又要浪费时间。


一,servlet容器对url的匹配过程:

     当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如我访问的是http://localhost/test/aaa.html,我的应用上下文是test,容器会将http://localhost/test去掉,剩下的/aaa.html部分拿来做servlet的映射匹配。这个映射匹配过程是有顺序的,而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了(filter不同,后文会提到)。其匹配规则和顺序如下:


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


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


     3. 扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet。例子:servletA的url-pattern:*.action


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

 

     根据这个规则表,就能很清楚的知道servlet的匹配过程,所以定义servlet的时候也要考虑url-pattern的写法,以免出错。
     对于filter,不会像servlet那样只匹配一个servlet,因为filter的集合是一个链,所以只会有处理的顺序不同,而不会出现只选择一个filter。Filter的处理顺序和filter-mapping在web.xml中定义的顺序相同。

 

 二,url-pattern详解


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

     1.以”/’开头和以”/*”结尾的是用来做路径映射的。


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


     3.“/” 是用来定义default servlet映射的。


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

 

     所以,为什么定义”/*.action”这样一个看起来很正常的匹配会错?因为这个匹配即属于路径映射,也属于扩展映射,导致容器无法判断。

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:jsp="http://java.sun.com/xml/ns/javaee/jsp" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>CVTI_BHMC</display-name> <security-constraint> <display-name>Forbidden</display-name> <web-resource-collection> <web-resource-name>Http Method Contraint</web-resource-name> <url-pattern>/*</url-pattern> <http-method>PUT</http-method> <http-method>DELETE</http-method> <http-method>TRACE</http-method> <http-method>OPTIONS</http-method> </web-resource-collection> <auth-constraint /> </security-constraint> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> <filter> <filter-name>HTMLTagFilter</filter-name> <filter-class>able.com.web.filter.HTMLTagFilter</filter-class> </filter> <filter-mapping> <filter-name>HTMLTagFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> <!-- J2534 전송 테그 필터 적용 해야하는지 확인해야함 안하도록 우선 적용 --> <!-- <filter> <filter-name>HTMLTagFilter2</filter-name> <filter-class>com.cvti.core.HTMLTagFilter</filter-class> </filter> <filter-mapping> <filter-name>HTMLTagFilter2</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:spring/context-*.xml</param-value> </context-param> <context-param> <param-name>contextInitialTaskingFactory</param-name> <param-value>able.com.web.context.ContextInitialTaskingFactory</param-value> </context-param> <session-config> <session-timeout>120</session-timeout> </session-config> <listener> <listener-class>able.com.web.context.ContextListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/springmvc/dispatcher-servlet*.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>/na/getToken.action</url-pattern> </servlet-mapping> <servlet> <servlet-name>action2</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/j2534/dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action2</servlet-name> <url-pattern>*.action</url-pattern> <url-pattern>*.bin</url-pattern> <url-pattern>*.BIN</url-pattern> <url-pattern>*.zip</url-pattern> </servlet-mapping> <servlet> <servlet-name>tilesDispatcher</servlet-name> <servlet-class>org.apache.tiles.web.util.TilesDispatchServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>tilesDispatcher</servlet-name> <url-pattern>*.tiles</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <login-config> <auth-method>BASIC</auth-method> </login-config> <!-- <resource-ref> <res-ref-name>jndi/CVTIHME</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> --> <jsp-config> <jsp-property-group> <url-pattern>*.jsp</url-pattern> <page-encoding>UTF-8</page-encoding> <include-prelude>/WEB-INF/jsp/include/declare.jspf</include-prelude> </jsp-property-group> </jsp-config> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/WEB-INF/jsp/com/error.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/WEB-INF/jsp/com/error404.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/WEB-INF/jsp/com/error.jsp</location> </error-page> </web-app> 什么意思
最新发布
01-09
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值