url-pattern

问题:为什么我使用“/”时 jsp没有被拦截,而其他包括css等静态资源都会被拦截而“/*”将会拦截所有资源?

 

 

准备知识:

 

一、url-pattern详解:

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

2、以前缀”*.”开头的是用来做后缀(或称扩展)映射的。

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

但是 你只能选择路径或者后缀映射,而不能同时用使用这两种映射,因为这样容器无法判断!例如这样的映射“/*.action

 

二、servlet 匹配规则:

当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url

比如我访问的是 http://localhost/test/aaa.html,我的应用上下文是test,容器会将http://localhost/test去掉,

剩下的/aaa.html部分拿来做servlet的映射匹配。这个映射匹配过程是有顺序的,而且当有一个servlet匹配成功以后,

就不会去理会剩下 的servlet.

其匹配规则和顺序如下:

1》精确路径匹配。例子:比如servletA url-pattern /testservletBurl-pattern /*

   这个时候,如果我访问的urlhttp://localhost/test

   这个时候容器就会先 进行精确路径匹配,发现/test正好被servletA精确匹配,

   那么就去调用servletA,也不会去理会其他的servlet了。

2》最长路径匹配。例子:servletAurl-pattern/test/*,而servletBurl-pattern/test/a/*

   此 时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB

3》扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet

   例子:servletAurl-pattern*.action

4》如果前面三条规则都没有找到一个servlet,容器会根据url选择对应的请求资源。

   如果应用定义了一个default servlet,则容器会将请求丢给default servlet(什么是default servlet?就是以“default”配置的serverlet)。

 

总结以上规则可细化为以下便于记忆:

1/abc/* ------1

2/* ------2

3/abc ------3

4*.do ------4

5/

 

 

三、tomcat的 “default servlet”和“jsp 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-mapping>

        <servlet-name>default</servlet-name>

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

</servlet-mapping>

 

 

<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>jsp</servlet-name>

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

    </servlet-mapping>

 

    <servlet-mapping>

        <servlet-name>jsp</servlet-name>

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

</servlet-mapping>

 

四、对问题的解释

 

当你的spring mvc 的“dispatcher servlet”配置为:“/” 时,

它会替换掉“default servlet”,此时“jsp  servlet”先拦截,如果拦截失败 会才采用“default servlet”也即“dispatcher servlet”!

显然:此时除了jspjspx外,dispatch servlet将拦截所有资源!

 

当你使用“/*”时,显然它会拦截所有资源,包括“jspjspxjscss等”

 

当你使用“*.action”时,

显然对于“.jsp.jspx”会被“jsp servlet”拦截。

对于“.js.css”会被“的“dispatcher servlet”拦截。

对于“.action”会被“dispatcher servlet”拦截。

 

 

五、当spring mvc 使用“/”或者“/*”时如何放过像“js等静态资源”?

解决办法1:在项目的web.xml加入如下代码:

<servlet-mapping>

        <servlet-name>default</servlet-name>

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

</servlet-mapping>

这样的话 会优先匹配“*.htm!

 

解决办法2:采用<mvc:default-servlet-handler />

 

 

springMVC-servlet.xml中配置<mvc:default-servlet-handler />后,

会在Spring MVC上下文中定义一个org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler

它会像一个检查员,对进入DispatcherServletURL进行筛查,如果发现是静态资源的请求,

就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。

一般Web应用服务器默认的Servlet名称是"default",因此DefaultServletHttpRequestHandler可以找到它。

如果你所有的Web应用服务器的默认Servlet名称不是"default",则需要通过default-servlet-name属性显示指定:

<mvc:default-servlet-handler default-servlet-name="所使用的Web服务器默认使用的Servlet名称" />

 

 

解决办法3:采用<mvc:resources />

<mvc:default-servlet-handler />将静态资源的处理经由Spring MVC框架交回Web应用服务器处理。而<mvc:resources />更进一步,

Spring MVC框架自己处理静态资源,并添加一些有用的附加值功能。

 

首先,<mvc:resources />允许静态资源放在任何地方,如WEB-INF目录下、类路径下等,你甚至可以将JavaScript等静态文件打到JAR包中。

通过location属性指定静态资源的位置,由于location属性是Resources类型,因此可以使用诸如"classpath:"等的资源前缀指定资源位置。

传统Web容器的静态资源只能放在Web容器的根路径下,<mvc:resources />完全打破了这个限制。

 

其次,<mvc:resources />依据当前著名的Page SpeedYSlow等浏览器优化原则对静态资源提供优化。

你可以通过cacheSeconds属性指定静态资源在浏览器端的缓存时间,一般可将该时间设置为一年,以充分利用浏览器端的缓存。

在输出静态资源时,会根据配置设置好响应报文头的Expires Cache-Control值。

 

在接收到静态资源的获取请求时,会检查请求头的Last-Modified值,如果静态资源没有发生变化,则直接返回303相应状态码,

提示客户端使用浏览器缓存的数据,而非将静态资源的内容输出到客户端,以充分节省带宽,提高程序性能。

 

springMVC-servlet中添加如下配置:

<mvc:resources location="/,classpath:/META-INF/publicResources/" mapping="/resources/**"/>

以上配置将Web根路径"/"及类路径下 /META-INF/publicResources/ 的目录映射为/resources路径。

假设Web根路径下拥有imagesjs这两个资源目录,images下面有bg.gif图片,在js下面有test.js文件,

则可以通过 /resources/images/bg.gif /resources/js/test.js 访问这二个静态资源。

 

假设WebRoot还拥有images/bg1.gif js/test1.js,则也可以在网页中通过 /resources/images/bg1.gif

/resources/js/test1.js 进行引用。  

猜你喜欢

转载自chtblyl0920052505.iteye.com/blog/2268363