Spring Boot静态资源处理

    <!-- 文章内容 -->
<div data-note-content="" class="show-content">
<div class="show-content-free">
<h1>8.8 Spring Boot静态资源处理</h1>

当使用Spring Boot来开发一个完整的系统时,我们往往需要用到前端页面,这就不可或缺地需要访问到静态资源,比如图片、css、js等文件。

Spring Boot使用 WebMvcAutoConfiguration 中的配置各种属性, 默认为我们提供了静态资源处理。如果需要特殊处理的再通过配置进行修改。

我们来看一下WebMvcAutoConfiguration类里面的默认配置。

静态资源默认配置WebMvcAutoConfiguration

在WebMvcAutoConfiguration类里面有个addResourceHandlers方法:

        @Override

public void addResourceHandlers(ResourceHandlerRegistry registry) {

if (!this.resourceProperties.isAddMappings()) {

logger.debug("Default resource handling disabled");

return;

}

Integer cachePeriod = this.resourceProperties.getCachePeriod();

if (!registry.hasMappingForPattern("/webjars/**")) {

customizeResourceHandlerRegistration(

registry.addResourceHandler("/webjars/**")

.addResourceLocations(

"classpath:/META-INF/resources/webjars/")

.setCachePeriod(cachePeriod));

}

String staticPathPattern = this.mvcProperties.getStaticPathPattern();

if (!registry.hasMappingForPattern(staticPathPattern)) {

customizeResourceHandlerRegistration(

registry.addResourceHandler(staticPathPattern)

.addResourceLocations(

this.resourceProperties.getStaticLocations())

.setCachePeriod(cachePeriod));

}

}

其中,针对webjars做了默认的处理:

registry.addResourceHandler("/webjars/**")

.addResourceLocations(

"classpath:/META-INF/resources/webjars/")

其中,如果当前的ResourceHandlerRegistry里面资源映射没有 “/**”, 则启用SpringBoot内置默认的静态资源处理:

String staticPathPattern = this.mvcProperties.getStaticPathPattern();//"/**"
        <span class="hljs-keyword">if</span> (!registry.hasMappingForPattern(staticPathPattern)) {</br>
customizeResourceHandlerRegistration(</br>
registry.addResourceHandler(staticPathPattern)</br>
.addResourceLocations(</br>
<span class="hljs-keyword">this</span>.resourceProperties.getStaticLocations())</br>
.setCachePeriod(cachePeriod));</br>
}</br>

默认的静态资源映射路径在ResourceProperties类里面,相关代码如下:

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {

"classpath:/META-INF/resources/", "classpath:/resources/",

"classpath:/static/", "classpath:/public/" };

<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String[] RESOURCE_LOCATIONS;</br></br>

<span class="hljs-keyword">static</span> {</br>
RESOURCE_LOCATIONS = <span class="hljs-keyword">new</span> String[CLASSPATH_RESOURCE_LOCATIONS.length</br>
+ SERVLET_RESOURCE_LOCATIONS.length];</br>
System.arraycopy(SERVLET_RESOURCE_LOCATIONS, <span class="hljs-number">0</span>, RESOURCE_LOCATIONS, <span class="hljs-number">0</span>,</br>
SERVLET_RESOURCE_LOCATIONS.length);</br>
System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, <span class="hljs-number">0</span>, RESOURCE_LOCATIONS,</br>
SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length);</br>
}</br></br> <span class="hljs-comment">/**</br>
* Locations of static resources. Defaults to classpath:[/META-INF/resources/,</br>
* /resources/, /static/, /public/] plus context:/ (the root of the servlet context).</br>
*/</span></br>
<span class="hljs-keyword">private</span> String[] staticLocations = RESOURCE_LOCATIONS;</br>

即默认配置的 /** 映射到如下目录:

classpath:/META-INF/resources/

classpath:/resources/

classpath:/static/

classpath:/public/

综上所述,Spring Boot 默认配置为:

页面请求路径模式 静态资源在工程的路径 优先级
/** classpath:/META-INF/resources/ 第1优先
/** classpath:/resources/ 第2优先
/** classpath:/META-INF/resources/ 第3优先
/** classpath:/static/ 第4优先
/webjars/** classpath:/META-INF/resources/webjars/ -

自定义静态资源映射

在SpringBoot集成Swagger的时候,我们需要增加swagger-ui.html映射到classpath:/META-INF/resources/,我们自定义配置类,继承WebMvcConfigurerAdapter,然后重写addResourceHandlers方法:

@Configuration

//@EnableWebMvc //这个注解会覆盖掉SpringBoot的默认的静态资源映射配置

class WebMvcConfig extends WebMvcConfigurerAdapter {

@Override

void addResourceHandlers(ResourceHandlerRegistry registry) {

    <span class="hljs-comment">//Swagger ui Mapping</span></br>
registry.addResourceHandler(<span class="hljs-string">"swagger-ui.html"</span>)</br>
.addResourceLocations(<span class="hljs-string">"classpath:/META-INF/resources/"</span>)</br></br> }</br></br>

}


如果想要自己完全控制WebMVC(完全覆盖SpringBoot默认配置),就需要在@Configuration注解的配置类上增加@EnableWebMvc,当增加@EnableWebMvc注解以后,WebMvcAutoConfiguration中配置就不会生效,会自动覆盖了官方给出的/static, /public, META-INF/resources, /resources等存放静态资源的目录。而将静态资源定位于src/main/webapp。

在spring-boot-features.adoc中指出,如果你的应用要打成jar形式来运行的话,不要把静态资源放到src/main/webapp目录,虽然这是标准目录,但是仅在打war包的时候起作用。因为大多数的构建工具在打jar包的时候,会默认忽略此目录:

TIP: Do not use the src/main/webapp directory if your application will be packaged as a

jar. Although this directory is a common standard, it will only work with war packaging

and it will be silently ignored by most build tools if you generate a jar.

当需要重新定义好资源所在目录时,则需要主动添加上述的那个配置类,来Override addResourceHandlers方法。你需要自己来配置需要的每一项。

这种方式会在默认的基础上增加

swagger-ui.html映射到classpath:/META-INF/resources/

不会影响默认的方式,可以同时使用。

前端资源的引用方法

在index.ftl中该如何引用上面的静态资源呢?

推荐默认的写法如下:

<link rel="stylesheet" type="text/css" href="/css/index.css">
<script type="text/javascript" src="/js/index.js"></script>

注意:默认配置的/**映射到/static(或/public ,/resources,/META-INF/resources)

当请求/css/index.css的时候,Spring MVC 会在/static/目录下面找到。

如果配置为/static/js/index.js

<script src="${request.contextPath}/static/js/index.js"></script>

那么上面配置的几个目录下面都没有/static目录,因此会找不到资源文件。

这个时候,就需要另外添加自定义的映射了:

registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")

所以,当我们使用SpringBoot默认静态资源配置的时候,写静态资源位置不要带上映射的目录名(如/static/,/public/ ,/resources/,/META-INF/resources/)。

使用WebJars

Spring Boot 在支持 Spring MVC的静态资源处理的特性的同时, 允许使用jar包版本的静态资源和使用版本无关的URL的静态资源的引用。它就是Webjars[1]。

例如,使用jQuery,添加依赖:

compile group: 'org.webjars.bower', name: 'jquery', version: '3.2.1'

然后,在前端html代码中,就可以直接如下使用:

<script type="text/javascript" src="/webjars/jquery/3.2.1/jquery.js"></script>

你可能注意到href中的1.11.3版本号了,如果仅仅这么使用,那么当我们切换版本号的时候还要手动修改href,比较麻烦。我们完全可以约定一套目录规则,把后端webjars的依赖版本,直接传递到后端。而负责完成维护管理这套目录规则的人就是webjars-locator。webjars-locator通过在classpath中寻找需要加载的静态资源,然后引入前端页面。查找路径的逻辑的方法是WebJarAssetLocator类里的getFullPath方法。

我们要想使用webjars-locator,先要添加依赖:

    //Group: org.webjars.bower
// https://mvnrepository.com/artifact/org.webjars/webjars-locator
compile group: 'org.webjars', name: 'webjars-locator', version: '0.32'

然后,增加一个WebJarController:

package com.easy.springboot.h5perf.controller

import org.springframework.core.io.ClassPathResource


import org.springframework.http.HttpStatus


import org.springframework.http.ResponseEntity


import org.springframework.stereotype.Controller


import org.springframework.web.bind.annotation.PathVariable


import org.springframework.web.bind.annotation.RequestMapping


import org.springframework.web.bind.annotation.ResponseBody


import org.springframework.web.servlet.HandlerMapping


import org.webjars.WebJarAssetLocator

import javax.servlet.http.HttpServletRequest

/**
  • Created by jack on 2017/4/22.


    */


    @Controller


    class WebJarsController {


    WebJarAssetLocator assetLocator = new WebJarAssetLocator();

    @ResponseBody


    @RequestMapping("/webjarslocator/{webjar}/**")


    def ResponseEntity<?> locateWebjarAsset(@PathVariable String webjar, HttpServletRequest request) {


    try {


    String mvcPrefix = "/webjarslocator/" + webjar + "/"; // This prefix must match the mapping path!


    String mvcPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);


    String fullPath = assetLocator.getFullPath(webjar, mvcPath.substring(mvcPrefix.length()));


    return new ResponseEntity<>(new ClassPathResource(fullPath), HttpStatus.OK);


    } catch (Exception e) {


    return new ResponseEntity<>(HttpStatus.NOT_FOUND);


    }


    }


    }

然后,前端代码使用方式如下:

<link href="${request.contextPath}/webjarslocator/datatables/jquery.dataTables.min.css" rel="stylesheet" type="text/css">

<link href="${request.contextPath}/webjarslocator/tether/tether.min.css" rel="stylesheet" type="text/css">

<link href="${request.contextPath}/css/index.css" rel="stylesheet" type="text/css">

<link href="${request.contextPath}/css/report.css" rel="stylesheet" type="text/css">

<script src="${request.contextPath}/webjarslocator/jquery/jquery.min.js"></script>


<script src="${request.contextPath}/js/index.js"></script>

<script src="${request.contextPath}/webjarslocator/tether/tether.min.js"></script>


<script src="${request.contextPath}/webjarslocator/bootstrap/bootstrap.min.js"></script>


<script src="${request.contextPath}/webjarslocator/datatables/jquery.dataTables.min.js"></script>

这里是freemarker的模板view代码示例。其中,request对象是内置对象。在application.yml配置如下:

spring:

# 在freemarker获取request对象

freemarker:

request-context-attribute: request

注意:这里不需要在写版本号了,但是注意写url的时候,只是在原来url基础上去掉了版本号,其他的都不能少!

静态资源动态版本

当我们资源内容发生变化时,由于浏览器缓存,用户本地的静态资源还是旧的资源,为了防止这种情况导致的问题,我们在请求url的时候加个版本号。

版本号如:

<script type="text/javascript" src="/js/index.js?v=1.0.1"></script>

这个版本号1.0.1,可以由后端代码传到前端页面${version}。

小结

本章节主要探讨了Spring Boot 静态资源处理的内容。当我们在开发中,遵循SpringBoot的默认配置,可以大大减少了我们静态资源处理的工作。

本章节完整的工程代码:

https://github.com/EasySpringBoot/h5perf

参考资料:

1.WebJars:http://www.webjars.org/

      </div>
</div>
</div>

Spring Boot静态资源处理的更多相关文章

  1. Spring Boot 静态资源处理

    spring Boot 默认的处理方式就已经足够了,默认情况下Spring Boot 使用WebMvcAutoConfiguration中配置的各种属性. 建议使用Spring Boot 默认处理方式 ...

  2. Spring Boot 静态资源处理(转)

    Spring Boot 静态资源处理 Spring Boot 系列 Spring Boot 入门 Spring Boot 属性配置和使用 Spring Boot 集成MyBatis Spring Bo ...

  3. 从零开始的Spring Boot(3、Spring Boot静态资源和文件上传)

    Spring Boot静态资源和文件上传 写在前面 从零开始的Spring Boot(2.在Spring Boot中整合Servlet.Filter.Listener的方式) https://www. ...

  4. 十二、 Spring Boot 静态资源处理

    spring Boot 默认为我们提供了静态资源处理,使用 WebMvcAutoConfiguration 中的配置各种属性. 建议大家使用Spring Boot的默认配置方式,如果需要特殊处理的再通 ...

  5. Spring Boot 静态资源路径分析

    最近在接触一个看公司的java后台项目(采用的耶鲁大学开源的一个cas单点登录系统),用的是框架是Spring Boot,用的模板是Thymeleaf,于是我生成一个Spring Boot的项目,并且 ...

  6. Spring Boot 静态资源访问原理解析

    一.前言 springboot配置静态资源方式是多种多样,接下来我会介绍其中几种方式,并解析一下其中的原理. 二.使用properties属性进行配置 应该说 spring.mvc.static-pa ...

  7. Spring Boot 静态资源映射与上传文件路由配置

    默认静态资源映射目录 默认映射路径 在平常的 web 开发中,避免不了需要访问静态资源,如常规的样式,JS,图片,上传文件等;Spring Boot 默认配置对静态资源映射提供了如下路径的映射 /st ...

  8. Spring Boot 静态资源能加载css 不能加载js

    Spring Boot 配置拦截器的时候默认 是放行 静态资源 , 也就是说不需要进行配置 registry.addResourceHandler("/**") .addResou ...

  9. Spring Boot 静态资源处理,妙!

    作者:liuxiaopeng https://www.cnblogs.com/paddix/p/8301331.html 做web开发的时候,我们往往会有很多静态资源,如html.图片.css等.那如 ...

随机推荐

  1. AD9850驱动程序--MSP430版本

    前段时间忙着画板子搞运放搞滤波了,程序更新的少,发现MSP430不是太好用,尤其Timer,不过也与我使用内部晶振有关,产生正玄波之前用MSP430发出PWM,再进行滤波变为正弦波太麻烦了,这次改用D ...

  2. struts2基础学习----struts.xml配置文件

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "- ...

  3. 无限极分类算法 thinkphp

    <?php/** 本类实现的是无限级递归分类的管理*/class InfiniteLevel{ public $id_str=""; public function add_ ...

  4. bzoj1433[ZJOI2009]假期的宿舍(匈牙利)

    1433: [ZJOI2009]假期的宿舍 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2544  Solved: 1074 [Submit][St ...

  5. 基于Spark Streaming预测股票走势的例子(二)

    上一篇博客中,已经对股票预测的例子做了简单的讲解,下面对其中的几个关键的技术点再作一些总结. 1.updateStateByKey 由于在1.6版本中有一个替代函数,据说效率比较高,所以作者就顺便研究 ...

  6. HTML--使用单选框、复选框,让用户选择

    在使用表单设计调查表时,为了减少用户的操作,使用选择框是一个好主意,html中有两种选择框,即单选框和复选框,两者的区别是单选框中的选项用户只能选择一项,而复选框中用户可以任意选择多项,甚至全选.请看 ...

  7. 分享两篇关于ActionBar样式设置的博客

    http://www.open-open.com/lib/view/open1373981182669.html http://blog.csdn.net/xyz_lmn/article/detail ...

  8. [python] ThreadPoolExecutor线程池

    初识 Python中已经有了threading模块,为什么还需要线程池呢,线程池又是什么东西呢?在介绍线程同步的信号量机制的时候,举得例子是爬虫的例子,需要控制同时爬取的线程数,例子中创建了20个线程 ...

  9. jsp里post和get的乱码解决问题

    6.乱码问题01:<%reques.setCharacterEncoding("utf-8");%> 02:get请求乱码 001.:String 编码之后的字符串 = ...

  10. python 根据数组生成图片

    array = np.asarray(allBigPng, dtype=np.uint8)image = Image.fromarray(array, 'RGBA') image.save(outpu ...