При обслуживании статических ресурсов обычной практикой является добавление некоторой информации о версии к URL-адресу ресурса. Это позволяет браузеру кешировать ресурсы неограниченное время. Всякий раз, когда изменяется содержимое ресурса, информация о версии в URL также изменяется. Обновленный URL-адрес заставляет браузер клиента отказаться от кэшированного ресурса и перезагрузить последнюю версию ресурса с сервера.
В Spring для настройки версионных URL-адресов ресурсов требуется всего два простых шага. В этом посте мы увидим, как это работает.
Обслуживание версионных URL
Сначала мы должны сказать Spring, что ресурсы должны быть доступны через версионный URL. Это делается в конфигурации MVC обработчика ресурсов:
@Configuration
public class MvcApplication extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
VersionResourceResolver versionResourceResolver = new VersionResourceResolver()
.addVersionStrategy(new ContentVersionStrategy(), "/**");
registry.addResourceHandler("/javascript/*.js")
.addResourceLocations("classpath:/static/")
.setCachePeriod(60 * 60 * 24 * 365) /* one year */
.resourceChain(true)
.addResolver(versionResourceResolver);
}
...
}
Здесь мы создаем обработчик ресурсов для файлов JavaScript, расположенных в папке с именем static внутри classpath. Период кэширования для этих файлов JavaScript установлен на один год. Важной частью является VersionResourceResolver, который поддерживает URL ресурсов с информацией о версии. VersionStrategy используется для получения фактической версии для ресурса.
В этом примере мы используем ContentVersionStrategy . Эта реализация VersionStrategy вычисляет хеш MD5 из содержимого ресурса и добавляет его к имени файла.
Например: предположим, у нас есть файл JavaScript test.js в каталоге classpath: / static /. Хеш MD5 для test.js равен 69ea0cf3b5941340f06ea65583193168.
Теперь мы можем отправить запрос
/javascript/test-69ea0cf3b5941340f06ea65583193168.js
который будет преобразован в classpath: /static/test.js.
Обратите внимание, что все еще можно запросить ресурс без хеша MD5. Так что этот запрос тоже работает:
/javascript/test.js
Альтернативной реализацией VersionStrategy является FixedVersionStrategy . FixedVersionStrategy использует фиксированную строку версии, которая добавляется в качестве префикса к пути ресурса.
Например:
/v1.2.3/javascript/test.js
Генерация версионных URL
Теперь нам нужно убедиться, что приложение генерирует URL ресурсов, которые содержат хеш MD5.
Одним из подходов для этого является использование ResourceUrlProvider . С помощью ResourceUrlProvider URL ресурса (например, /javascript/test.js) можно преобразовать в версионный URL (например, /javascript/test-69ea0cf3b5941340f06ea65583193168.js). Bean-компонент ResourceUrlProvider с идентификатором mvcResourceUrlProvider автоматически объявляется в конфигурации MVC.
Если вы используете Thymeleaf в качестве механизма шаблонов, вы можете получить доступ к компоненту ResourceUrlProvider напрямую из шаблонов, используя синтаксис @bean.
Например:
<script type="application/javascript"
th:src="${@mvcResourceUrlProvider.getForLookupPath('/javascript/test.js')}">
</script>
Если вы используете шаблонизатор, который не дает вам прямого доступа к бинам Spring, вы можете добавить компонент ResourceUrlProvider в атрибуты модели. Используя ControllerAdvice , это может выглядеть так:
@ControllerAdvice
public class ResourceUrlAdvice {
@Inject
ResourceUrlProvider resourceUrlProvider;
@ModelAttribute("urls")
public ResourceUrlProvider urls() {
return this.resourceUrlProvider;
}
}
Внутри представления мы можем получить доступ к ResourceUrlProvider, используя атрибут модели urls:
<script type="application/javascript"
th:src="${urls.getForLookupPath('/javascript/test.js')}">
</script>
Этот подход должен работать со всеми шаблонизаторами, которые поддерживают вызовы методов.
Альтернативный подход для создания версионных URL-адресов — это использование ResourceUrlEncodingFilter . Это фильтр сервлетов, который переопределяет метод HttpServletResponse.encodeURL () для генерации версионных URL ресурсов.
Чтобы использовать ResourceUrlEncodingFilter, нам просто нужно добавить дополнительный компонент в наш класс конфигурации:
@SpringBootApplication
public class MvcApplication extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// same as before ..
}
@Bean
public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
return new ResourceUrlEncodingFilter();
}
...
}
Если используемый вами шаблонизатор вызывает метод encodeURL () ответа, информация о версии будет автоматически добавлена в URL. Это будет работать в JSP, Thymeleaf, FreeMarker и Velocity.
Например: с Thymeleaf мы можем использовать стандартный синтаксис @ {..} для создания URL:
<script type="application/javascript" th:src="@{/javascript/test.js}"></script>
Это приведет к:
<script type="application/javascript"
src="/javascript/test-69ea0cf3b5941340f06ea65583193168.js">
</script>
Резюме
Добавление информации о версии к URL-адресам ресурсов является обычной практикой для максимального кэширования браузера. В Spring нам просто нужно определить VersionResourceResolver и VersionStrategy для обслуживания версионных URL-адресов. Самый простой способ создания версионных URL-адресов внутри шаблонизаторов — это использование ResourceUrlEncodingFilter.
Если стандартные реализации VersionStrategy не соответствуют вашим требованиям, вы можете создать нашу собственную реализацию VersionStrategy.
Вы можете найти полный пример исходного кода на GitHub .