博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
springMVC对静态资源访问的处理
阅读量:5920 次
发布时间:2019-06-19

本文共 3957 字,大约阅读时间需要 13 分钟。

hot3.png

在restful  风格下springMVC会进行如下配置

  
            
mvc
      
org.springframework.web.servlet.DispatcherServlet
       
                  
contextConfigLocation
                  
/WEB-INF/classes/conf/spring/mvc-*.xml
         
         
1
    
  
      
mvc
       
/
     

        很明显,该 servlet 对应的 url-pattern 定义成 /,因此该 servlet 会匹配上诸如 /images/a.jpg, /css/hello.css 等这些静态资源,甚至包括 /jsp/stock/index.jsp 这些 jsp 也会匹配。但是并没有定义相应的 Controller 来处理这些资源,因此这些请求通常是无法完成的。 
        很麻烦?没有 Struts 方便?此言差矣,因此你在 Struts 定义其核心 filter 的 url-pattern 是 *.action,当然不会对处理 jsp 和静态资源操作影响了。Spring MVC 若也定义类似的 url-pattern,同样不存在问题。 
        说到这里,我们应该想一个问题。Tomcat 中,只有 servlet 能够处理请求,即使是 jsp,也会被编译成 servlet。我们即便使用 Struts,定义 *.action 的url-pattern,那 .css, *.gfi 等这些静态资源到底是谁来处理了???你可不要想当然的认为我不是输入了图片的路径了吗?如,/images/a/b/c.gif。请注意,servlet 容器中,只有 servlet 采用处理资源! 
        由 servlet 处理这些资源那是一定了。不过,不同的 servlet 容器/应用服务器,处理这些静态资源的 servlet 的名字不大一样: 

  • Tomcat, Jetty, JBoss, and GlassFish:默认 Servlet 名字为 "default"

  • Google App Engine:默认 Servlet 名字为 "_ah_default"

  • Resin:默认 Servlet 名字为 "resin-file"

  • WebLogic:默认 Servlet 名字为 "FileServlet"

  • WebSphere:默认 Servlet 名字为 "SimpleFileServlet"

    ◇ 方案一:激活 Tomcat 的 defaultServlet 来处理静态资源 

<servlet-mapping>  

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

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

</servlet-mapping>  

<servlet-mapping>  

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

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

</servlet-mapping>  

<servlet-mapping>  

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

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

</servlet-mapping>  

        每种类型的静态资源需要分别配置一个 servlet-mapping,同时,要写在 DispatcherServlet 的前面, 让 defaultServlet 先拦截。 

但是这样还会有个问题,就是无法访问到classpath下的资源文件,看了tomcat的DefaultServlet的配置项,似乎也没有可以指定目录的地方。

    ◇ 方案二:Spring 3.0.4 以后版本提供了 <mvc:resources /> 

    

  1. <!-- 处理静态资源 -->  

  2.     <!-- 上传的图片缓存1个月,其他js,css,img资源缓存一年 -->  

  3.     <mvc:resources mapping="/res/**" location="/res/" cache-period="2592000"/>   

  4.     <mvc:resources mapping="/resources/**" location="/resources/" cache-period="31536000"/>   

  5.     <mvc:resources mapping="/css/**" location="/css/" cache-period="31536000"/>  

  6.     <mvc:resources mapping="/js/**" location="/js/" cache-period="31536000"/>  

  7.     <mvc:resources mapping="/img/**" location="/img/" cache-period="31536000"/>  

  8.     <mvc:resources mapping="/images/**" location="/images/" cache-period="31536000"/>  

       mapping 映射到 ResourceHttpRequestHandler 进行处理,location 指定静态资源的位置,可以是 web application 根目录下、jar 包里面,这样可以把静态资源压缩到 jar 包中。cache-period 可以使得静态资源进行 web cache。 

        使用 <mvc:resources /> 元素,会把 mapping 的 URI 注册到 SimpleUrlHandlerMapping 的 urlMap 中,key 为 mapping 的 URI pattern 值,而 value 为 ResourceHttpRequestHandler,这样就巧妙的把对静态资源的访问由 HandlerMapping 转到 ResourceHttpRequestHandler 处理并返回,所以就支持 classpath 目录, jar 包内静态资源的访问。 
    ◇ 方案三:使用 <mvc:default-servlet-handler /> 
        <mvc:default-servlet-handler /> 会把 "/**" url 注册到 SimpleUrlHandlerMapping 的 urlMap 中,把对静态资源的访问由 HandlerMapping 转到 org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler 处理并返回。DefaultServletHttpRequestHandler 使用就是各个 Servlet 容器自己的默认 Servlet。 
        补充说明下以上提到的 HandlerMapping 的 order 的默认值: 

  • DefaultAnnotationHandlerMapping:0

  • <mvc:resources /> 自动注册的 SimpleUrlHandlerMapping:2147483646

  • <mvc:default-servlet-handler/> 自动注册的 SimpleUrlHandlerMapping:2147483647

        Spring 会先执行 order 值比较小的。当访问一个 a.jpg 图片文件时,先通过 DefaultAnnotationHandlerMapping 来找处理器,一定是找不到的,我们没有叫 a.jpg 的 Controller。再按 order 值升序找,由于最后一个 SimpleUrlHandlerMapping 是匹配 "/**" 的,所以一定会匹配上,再响应图片。 

        Spring MVC 中,访问一个图片,还要走层层匹配。性能肯定好不到哪里去。不仅仅是 Spring MVC,即便 Struts,它们毕竟存活于 servlet 容器,只要由 servlet 容器处理这些静态资源,必然要将这些资源读入 JVM 的内存区中。所以,处理静态资源,我们通常会在前端加 apache 或 nginx。

另外,性能最好的应该是直接利用容器的DefaultServlet,让它最先拦截静态资源请求,这样就避免了后续的转发等操作,提高了性能,但是无法访问classpath下的资源文件。而通过mvc:resources标签可以简单配置匹配规则和资源文件路径,应该说是最简单快捷的一种方式,当然这大概也是mvc命名空间设计的初衷。

另外,若想结合两者的话,自己倒是可以尝试写一个Servlet或者filter来处理,不过估计有难度且麻烦。

--- add 2016-04-19

最近又想到一个办法,在java服务器前再增加一个http服务器处理静态资源,java服务器只处理动态资源,这样也可以啊

转载于:https://my.oschina.net/hnqingping1255/blog/415575

你可能感兴趣的文章
我的友情链接
查看>>
C#/Java/C/C++基本类型所占大小及表示范围
查看>>
nginx
查看>>
2月第4周国内域名商TOP10:51DNS净减2.3万 份额下跌
查看>>
一台服务器的黑道生涯(连载)之一 初入江湖(原创)
查看>>
我的友情链接
查看>>
简明 Git 命令速查表(中文版)
查看>>
ELK安装使用
查看>>
云HBase小组成功抢救某公司自建HBase集群,挽救30+T数据
查看>>
MSTP+OSPF+VRRP综合实验指导书
查看>>
大数据,处处充满商机,也充满了无限机遇
查看>>
作为一个SEO人员必须要具备的思维
查看>>
linux配置java环境变量(详细)
查看>>
Linux启动之GRUB错误
查看>>
Struts2笔记(5)-----Struts2的校验器
查看>>
Linux crontab 命令
查看>>
SHELL awk 及例子
查看>>
Altas在Ubuntu系统上的安装部署步骤
查看>>
nginx配置cache-control
查看>>
PostgreSQL的10进制与16进制互转
查看>>