1. 程式人生 > >Spring Boot靜態資源

Spring Boot靜態資源

Spring Boot靜態資源

Spring Boot靜態資源的存放位置

Spring Boot 提供了對靜態資源的支援,在建立Spring Boot專案時預設只建立了一個存放靜態資源的目錄src/main/resources/static,其它三個如果需要可以手動創建出目錄,而且這四個是有優先順序,當同一個資源出現在靜態目錄的多個地方時是按照優先順序獲取的,先獲取優先順序高的。

  1. classpath:/META-INF/resources
  2. classpath:/resources
  3. classpath:/static
  4. classpath:/public

在這裡插入圖片描述

1. application.properties配置

對應的原始碼:spring-configuration-metadata.json

{ 
	"sourceType": "org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties", 
	"defaultValue": "\/**", 
	"name"
: "spring.mvc.static-path-pattern", "description": "Path pattern used for static resources.", "type": "java.lang.String" }, { "sourceType": "org.springframework.boot.autoconfigure.web.ResourceProperties", "defaultValue": [ "classpath:\/META-INF\/resources\/", "classpath:\/resources\/", "classpath:\/static\/"
, "classpath:\/public\/" ], "name": "spring.resources.static-locations", "description": "Locations of static resources. Defaults to classpath:[\/META-INF\/resources\/,\n \/resources\/, \/static\/, \/public\/].", "type": "java.lang.String[]" },

對應application.properties的預設配置

spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/

在應用程式啟動的時候會有日誌列印,可以看到

  • /** 對映到 /static (或/public、/resources、/META-INF/resources)
  • /webjars/** 對映到 classpath:/META-INF/resources/webjars/在這裡插入圖片描述

比如 在src/main/resources/static目錄下放一個index.html, 通過http://localhost:8080/index.html就能直接訪問,路徑中不用在包含static子路徑了
如果訪問靜態資源想在路徑上有體現,也可以自定義,如將static-path-pattern配置成spring.mvc.static-path-pattern=/static/**就需要用http://localhost:8080/static/index.html來訪問
同樣如果對於系統定義的靜態資源的存放位置不滿意也可以通過spring.resources.static-locations來定義,一般靜態資源都放在src/main/resource下面

2. JavaConfig - WebMvcConfigurationSupport

addResourceHandlers用於配置spring.mvc.static-path-pattern
傳統Spring MVC開發經常將jsp頁面放置在webapp/WEB-INF下,這樣要想訪問頁面就需要寫一個controller對應的方法,即使方法中沒什麼業務邏輯,只僅僅用於頁面跳轉也不得不寫,在Spring Boot中通過配置addViewControllers,配置一個路徑和一個檢視名稱的對映即可,也不用再controller中寫頁面跳轉的RequestMapping方法了
在這裡插入圖片描述

webjars

webjars 就是將web開發中常用的靜態資源放到classpath:/META-INF/resources/webjars/ 中,然後打包成.jar釋出到maven倉庫中,使用時通過maven來引入,假如專案中用到jquery,常規的做法就是手動去官網下載,然後手動將bootstrap放到靜態目錄。一般常用的像jquery、bootstrap、angularjs、react、vue、swagger-ui等都有相應的maven依賴,目前有92個這種依賴。

<!-- jq -->
<dependency>
   <groupId>org.webjars</groupId>
   <artifactId>jquery</artifactId>
   <version>3.3.1</version>
</dependency>

在這裡插入圖片描述

在頁面上通過/webjars/jquery/3.3.1/jquery.js 來引入,Spring Boot 預設將 /webjars/** 對映到 classpath:/META-INF/resources/webjars/
可以通過http://localhost:8080/webjars/jquery/3.3.1/jquery.js來訪問

webjars-locator

在上面訪問靜態資源時路徑中包含了版本號(http://localhost:8080/webjars/jquery/3.3.1/jquery.js),假如版本升級需要全域性替換所有引入的檔案,webjars提供了一個webjars-locator的依賴,目的是讓前端頁面引入的靜態資源不包含路徑,當請求一個靜態資源時會自動幫你對映到對的版本對應的資源

<dependency>
   <groupId>org.webjars</groupId>
   <artifactId>webjars-locator</artifactId>
   <version>0.33</version>
</dependency>
@Controller
public class WebJarsController {

    private final WebJarAssetLocator assetLocator = new WebJarAssetLocator();

    @ResponseBody
    @RequestMapping("/webjarslocator/{webjar}/**")
    public ResponseEntity<Object> locateWebjarAsset(@PathVariable String webjar, HttpServletRequest request) {
        try {
            // /webjarslocator/jquery/
            String mvcPrefix = "/webjarslocator/" + webjar + "/"; // This prefix must match the mapping path!
            // /webjarslocator/jquery/jquery.js
            String mvcPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
            // META-INF/resources/webjars/jquery/3.3.1/jquery.js
            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);
        }
    }

}

訪問http://localhost:8080/webjarslocator/jquery/jquery.js(此地址中不包含版本號),地址對映到WebJarsController,返回META-INF/resources/webjars/jquery/3.3.1/jquery.js對應的資源。這樣就達到前端引入的靜態資源中不包含具體版本號,當需要升級的時候直接修改maven對應的依賴版本即可,前端也不用全域性替換版本號操作了

靜態資源瀏覽器快取

開發時,業務對應的js經常會變動,一般瀏覽器會快取靜態資源,一般防止瀏覽器快取靜態資源的做法是在地址後面使用版本號引數,或者在地址後面使用時間戳,Spring Boot 給出了自己的解決方案

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**

在這裡插入圖片描述
common.js放在 src/main/resources/static/js/目錄下
<script src="${pageContext.request.contextPath }${urls.getForLookupPath(’/js/common.js’) }"></script>
當我們訪問頁面後,HTML中實際生成的程式碼為common-.js, 每當common.js內容發生變化時MD5值就會重新生成,當js檔案沒有改變時md5值不變,當js檔案內容發生改變時,md5值發生變化,js檔案的內容也隨之改變。這樣就保證了js檔案始終是最新的。

Spring Boot Interceptor攔截器

攔截器的使用分兩步:

  1. 宣告攔截器,實現HandlerInterceptor
  2. 配置攔截器,在WebMvcConfigurerAdapter#addInterceptors配置
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println(request.getRequestURI() + "-------------");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("------------postHandle------------");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.out.println("------------afterCompletion------------");
    }
}
@Configuration
public class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");

        super.addResourceHandlers(registry);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**");
        super.addInterceptors(registry);
    }
}

訪問http://localhost/index.html會被攔截,而訪問http://localhost/static/index.html不會並攔截


轉載
Spring Boot入門教程(十九): Thymeleaf