专注Java教育14年 全国咨询/投诉热线:444-1124-454
赢咖4LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 SpringMVC静态资源处理

SpringMVC静态资源处理

更新时间:2021-12-09 12:07:18 来源:赢咖4 浏览1108次

由于早期的Spring MVC对静态资源的处理不好,DispatCherServlet的请求映射是在Web.xml中配置的,经常在*.do,*. Xhtml。这就决定了请求的 URL 必须是后缀 URL,不能使用真正的 REST 风格的 URL。

如果将 DispatcherServlet 请求映射配置为“”,则 Spring MVC 会捕获 Web 容器的所有请求,包括静态资源,Spring MVC 会将它们视为正常的请求过程,从而导致相应处理器的错误。

如何让Spring框架捕获所有的URL请求,同时从Web容器中传输静态资源,前提是DispatcherServlet的请求映射为“/”。由于REST是Spring的重要特性之一,因此Spring团队非常接近静态资源来处理这个任务,给出了两个经典的解决方案。

在学习这两个场景之前,调整Web.xml中DispatcherServlet的配置,使其能够捕获所有请求。

< servlet > 
  < servlet-name > smart </ servlet-name > 
  < servlet-class > org.springframework.web.servlet.DispatcherServlet </ servlet-class > 
  < load-on-startup > 1 </ load-on-startup > 
</小服务程序>
< servlet-mapping > 
  < servlet-name > smart </ servlet-name > 
  < url-pattern > / </ url-pattern > 
</ servlet-mapping >

所有的URL请求都会通过<url-pattern> /  </ url-pattern>的配置被Spring MVC的DispatcherServlet拦截。

1. 采用<MV: Default-servlet-handler />

在 smart-servlet.xml 中配置 <mvc: default-servlet-handler /> 后,您将在 Spring MVC 上下文中定义一个 org.springframework.web.servlet.resource.defaultservlettpRequestHandler,它将充当检查员的角色,输入用于筛选的 DispatcherServlet 的 URL。如果发现是静态资源请求,则转由WEB应用服务器默认servlet请求;如果不是静态资源请求,则继续由 DispatcherServlet 处理。

一般的web应用服务器(包括Tomcat、Jetty、GlassFish、JBoss、Resin、WebLogic和WebSphere)默认的servlet名称是default,所以defaultservlettpRequestHandler可以找到。如果用户使用的Web应用服务器的默认servlet名称不是default,则需要通过default-servlet-name属性明确指定。

< mvc:default-servlet-handler default—serv1et—name ="yourServerDefaultServlet Name" />

2. 使用<mvc:resources />

<mvc: default-servlet-handler />通过 Spring MVC 框架返回一个静态资源给 web 应用服务器。而 <mvc:resources /> 进一步由 Spring MVC 框架处理静态资源,并添加了一些有用的附加功能。

首先,<mvc:resources />允许静态资源放置在任何地方,比如web-inflicity、classpath等,甚至JavaScript等静态文件都可以打包到JAR包中。静态资源的位置由Location属性指定,由于location属性是资源类型,资源前缀指定资源前缀,如“ClassPath:”。传统Web容器的静态资源只能放在Web容器的根路径下,完全打破了这个限制。

其次,<mvc:resources />  提供基于当前浏览器优化原则如Page Speed、YSLOW 的静态资源优化。可以指定一个cacheseconds属性来指定浏览器端的缓存时间,一般设置为一年,以充分利用浏览器端。输出静态资源时,应根据配置设置文本的 expires 和 cache-control 值。

当接收到静态资源获取请求时,检查请求头的Last-Modified值。如果静态资源没有变化,直接返回303响应状态码,表示客户端使用浏览器缓存的数据,而不是将静态资源的内容输出给客户端到足够的带宽,提高程序性能。

在 smart-servlet.xml 中添加以下配置:

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

以上配置将web根路径“/”和类路径/meta-inf/publicresources/映射到/resources路径下。假设web根路径下有Images和JS两个资源目录,可以通过下图的方式来引用静态资源。

假设classpread/meta-inf/publicresources/下Images/Bg1.gif和JS/Test1.js也可以通过/resources/iImages/bg1.gif和/resources/js/test1.js在网页中进行引用,如以下代码所示。

< script src ="<c:url value=" / resources / js / test.js" /> " type= " text / javascript">< / script >

由于<mvc:resources />可以将多个物理路径映射到一个逻辑路径,所以一个逻辑路径所代表的资源存在于多个物理路径中。对于这个问题,<mvc:resources />的处理机制是只要找到匹配的资源,查找的顺序和Location中的物理路径按照Location的location中配置的顺序一致在物理路径下。

聪明的读者可能会问:既然网页根路径“/”映射了“/resources/**”,那么是否可以通过“/resources/web-inf/web.xml”访问网页中的这个敏感文件?答案是否定的。Spring MVC 在处理地图的静态资源时,会看到引用路径中是否包含Web-INF 或META-INF。如果包含,直接返回NULL值,保护安全文件不泄露。当然,如果/web-INF/Settings在location属性中,则可以通过/resources/web.xml的URL查看Web.xml。

< mvc:resources mapping ="/resources/**" location ="/WEB-INF/" />

所以在使用<mvc:resources />时要特别注意,不要在意,你不在意,你不要期望暴露的资源。

静态资源的缓存有效时间可以通过<mvc:resources />的cache-period属性在客户端浏览器中设置。

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

一般情况下,将cache-period 设置为一年,以充分利用客户端的缓存数据。

在发布新版本的app时,即使服务器端的JavaScript、CSS等静态资源文件发生了变化,但由于客户端浏览器本身的问题,客户端并没有从服务器端下载新的静态资源。一个好的解决办法是在Page的path中添加应用版本号,这个版本号被新的部署版本改变了,导致这些静态资源由于新的部署版本而变成这些静态资源。“新资源”,客户端浏览器下载这个“新资源”而不使用缓存中的数据。对于这个方案,可以通过<mvc:resources/>的静态资源逻辑路径给出一个通用的方案。

发布版本号包含在的静态资源逻辑路径中。首先创建一个servletContextaWare实现类,如下代码所示。

导入javax.servlet.ServletContext;
导入org.springframework.web.context.ServletContextAware;
公共 类ResourcePathExposer实现ServletContextAware {
     private ServletContext servletContext;
    私有字符串资源根;
    公共 无效初始化(){
        字符串版本= "1.2.1"; // 1 在实际应用中,可以将应用的发布版本号保存在外部属性文件或数据库中,这里可以获取。这里只有一个模拟值。
        resourceRoot = "/resources-" + 版本;// 2 发布资源逻辑路径上应用的版本号
        getServletContext().setAttribute("resourceRoot" ,
                getServletContext().getContextPath() +resourceRoot); // 3 在servletContext的属性列表的资源逻辑路径列表中
    }
    public  void setServletContext(ServletContext servletContext) {
         this .servletContext = servletContext;
    }
    公共字符串 getResourceRoot() {
        返回资源根;
    }
    公共ServletContext getServletContext() {
        返回servletContext;
    }    
}

在ResourcePatHexposer中获取应用的发布版本号,生成带有版本号的静态资源路径,将其值发布到servletContext,servletContext可以通过${resourceeroot}引用其值。

接下来,您要调整配置以使用静态资源逻辑路径的版本。

< bean id ="rpe" class ="com.smart.web.ResourcePathExposer" init-method ="init" /> 
< mvc:resources mapping ="#{rpe.resourceRoot}/**" location ="/"缓存-期间="31536000" />

将ResourcePatHexposer配置为1,并在init()中指定其初始化方法,以便在容器启动时初始化ResourceRoot的值。由于它实现了 servletContextaWare 接口,因此 Spring 将在 bean 的初始化中注入 servletContext 引用。

2处,通过Spring EL表达式引用resourceRootHexposer的resourceerOot属性值,生成动态静态资源逻辑路径。

最后调整在网页中引用静态资源的方式,如下代码所示。

< script src ="<c:url value=" ${resourceRoot}/js/test.js" /> " type= " text / javascript">< / script >

由于引用的resourceroot值和#{rpe.resourceroot}引用的<mvc:resources />,可以正确访问物理静态资源。这样,每次发布新版本后,客户端会自动下载新的静态资源,发布版本号发生变化。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>