Spring Boot靜態資源
Spring Boot靜態資源
- Spring Boot靜態資源的存放位置
- 1. application.properties配置
- 2. JavaConfig - WebMvcConfigurationSupport
- webjars
- webjars-locator
- 靜態資源瀏覽器快取
- Spring Boot Interceptor攔截器
Spring Boot靜態資源的存放位置
Spring Boot 提供了對靜態資源的支援,在建立Spring Boot專案時預設只建立了一個存放靜態資源的目錄src/main/resources/static,其它三個如果需要可以手動創建出目錄,而且這四個是有優先順序,當同一個資源出現在靜態目錄的多個地方時是按照優先順序獲取的,先獲取優先順序高的。
- classpath:/META-INF/resources
- classpath:/resources
- classpath:/static
- 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攔截器
攔截器的使用分兩步:
- 宣告攔截器,實現HandlerInterceptor
- 配置攔截器,在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不會並攔截