SpringMVC中关于静态资源的处理

image-20221117145622914

1、web项目中web.xml的配置

在一个使用springmvc的web项目中,必然在web.xml中要配置前端控制器 DispatcherServlet

<servlet>
  <servlet-name>springmvc</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <!-- 服务器启动的时候,让DispatcherServlet对象创建 -->
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>springmvc</servlet-name>
  <url-pattern>/</url-pattern> <!--注意这里-->
</servlet-mapping>

这里的 url-pattern 有两种配置方式:

  • 扩展名,比如.do,古老的方式,不会导致静态资源文件被拦截的问题,但 是不支持RESTful编码风格。
  • /,支持RESTful风格,但是会导致静态资源文件被拦截。

还有一种错误的配置方式:

  • /*,错误的方式,可以请求到Controller方法,但是跳转到JSP时会被拦截,JSP不能正常显示 XX。

一般来说,企业中更多的是采用第二种配置方式,但这导致了静态资源被拦截。

2、静态资源为什么会被拦截

我们知道,我们的web项目最终要部署到服务器上,以我们熟悉的Tomcat服务器为例进行说明。

当我们将web应用部署到tomcat服务器上,服务器是先加载全局的 web.xml ,即tomcat自带的web.xml文件,然后才会加载我们自己web项目中的 web.xml ,当我们把 url-pattern配置成 <url-pattern>/</url-pattern>会覆盖掉全局web.xml中对于静态资源的处理,具体可以参考全局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>


    <!-- The mapping for the default servlet -->
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

这就是默认的servlet,发现与我们配置的url-pattern一样了,导致静态资源也被我们自定义的dispatcherServlet所拦截,那这个类就会去找controller里面的映射了,比如我们访问http://localhost:8080/springmvc/img.png,显然是Controller里面是没有这个映射路径的。

3、如何过滤静态资源

首先要明白过滤的必要性:

一般来说,HTTP 请求都会被映射到 DispatcherServlet,进而由具体的类来承接处理,但对于类似 js 或者 css 这样的静态资源则没必要这样,因为对资源的获取只需返回资源本身即可,无需做其他处理,那么这时就需要对一系列的资源文件做过滤处理。

有三种方式:

  • 方式一:手动排除法

在我们的 web.xml 添加如下配置:

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.jpg</url-pattern>
    </servlet-mapping>

其他地方保持不变,这个粒度显然是比 <url-pattern>/</url-pattern>更小的,它会将*.jpg文件交给 servlet-name为default的servlet去处理该请求,默认的servlet为什么就没有拦截了呢?因为它是直接访问。

当然不好的地方是,如果你需要拦截 *.html又得配一个,所以比较麻烦。一般不采用。

  • 方式二:在springmvc的配置文件中加入<mvc:default-servlet-handler/>
<mvc:default-servlet-handler/>

在springMVC-servlet.xml中配置<mvc:default-servlet-handler />后,会在Spring MVC上下文中定义一个 org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它会像一个检查员,对进入DispatcherServlet的URL进行筛查,如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。

一般Web应用服务器默认的Servlet名称是"default",因此DefaultServletHttpRequestHandler可以找到它。如果你所有的Web应用服务器的默认Servlet名称不是"default",则需要通过default-servlet-name属性显示指定:

<mvc:default-servlet-handler default-servlet-name="所使用的Web服务器默认使用的Servlet名称" />
  • 方式三:在springmvc配置文件中手动指定静态资源路径
    <!-- 设置静态资源不过滤 -->
    <mvc:resources location="/css/" mapping="/css/**" />
    <mvc:resources location="/img/" mapping="/img/**" />
    <mvc:resources location="/js/" mapping="/js/**" />
    <mvc:resources location="/plugins/" mapping="/plugins/**" />

mapping属性为映射路径,location属性为本地静态资源路径。这种方式更灵活,功能更丰富,也是可以的。

还有静态资源放在WEB-INF目录下虽然在IDEA中运行没有问题,都可以进行访问,但是打包成war包放入tomcat中部署时会导致无法访问,所以我一般将静态资源放在和WEB-INF平级的目录下。

《参考文章》

Spring MVC 过滤静态资源访问 ——溪边静禅
<mvc:default-servlet-handler/>的作用 ——多弗朗明哥
SpringMVC中静态资源的处理 ——HeliusKing

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值