{"id":44154,"date":"2015-09-24T10:00:54","date_gmt":"2015-09-24T07:00:54","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=44154"},"modified":"2015-09-22T22:09:51","modified_gmt":"2015-09-22T19:09:51","slug":"resource-versioning-with-spring-mvc","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html","title":{"rendered":"Resource versioning with Spring MVC"},"content":{"rendered":"<p>When serving static resources, it is common practice to append some kind of version information to the resource URL. This allows the browser to cache resources for an unlimited time. Whenever the content of the resource is changed, the version information in the URL is changed too. The updated URL forces the client browser to discard the cached resource and reload the latest resource version from the server.<\/p>\n<p>With Spring it only takes two simple steps to configure versioned resource URLs. In this post we will see how it works.<\/p>\n<h2>Serving versioned URLs<\/h2>\n<p>First we need to tell Spring that resources should be accessible via a versioned URL. This is done in the resource handler MVC configuration:<\/p>\n<pre class=\" brush:java\">@Configuration\r\npublic\u00a0class\u00a0MvcApplication\u00a0extends\u00a0WebMvcConfigurerAdapter\u00a0{\r\n\r\n\u00a0\u00a0@Override\r\n\u00a0\u00a0public\u00a0void\u00a0addResourceHandlers(ResourceHandlerRegistry\u00a0registry)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0VersionResourceResolver\u00a0versionResourceResolver\u00a0=\u00a0new\u00a0VersionResourceResolver()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.addVersionStrategy(new\u00a0ContentVersionStrategy(),\u00a0\"\/**\");\r\n\r\n\u00a0\u00a0\u00a0\u00a0registry.addResourceHandler(\"\/javascript\/*.js\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.addResourceLocations(\"classpath:\/static\/\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.setCachePeriod(60\u00a0*\u00a060\u00a0*\u00a024\u00a0*\u00a0365)\u00a0\/*\u00a0one\u00a0year\u00a0*\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.resourceChain(true)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.addResolver(versionResourceResolver);\r\n\u00a0\u00a0}\r\n\r\n\u00a0\u00a0...\r\n}<\/pre>\n<p>Here we create a resource handler for JavaScript files located in folder named static inside the classpath. The cache period for these JavaScript files is set to one year. The important part is the <a title=\"Spring VersionResourceResolver API documentation\" href=\"http:\/\/docs.spring.io\/spring\/docs\/current\/javadoc-api\/org\/springframework\/web\/servlet\/resource\/VersionResourceResolver.html\">VersionResourceResolver<\/a> which supports resource URLs with version information. A <a title=\"Spring VersionStrategy API documentation\" href=\"http:\/\/docs.spring.io\/spring\/docs\/current\/javadoc-api\/org\/springframework\/web\/servlet\/resource\/VersionStrategy.html\">VersionStrategy<\/a> is used to obtain the actual version for a resource.<\/p>\n<p>In this example we use a <a title=\"Spring ContentVersionStrategy API documentation\" href=\"http:\/\/docs.spring.io\/spring\/docs\/current\/javadoc-api\/org\/springframework\/web\/servlet\/resource\/ContentVersionStrategy.html\">ContentVersionStrategy<\/a>. This VersionStrategy implementation calculates an MD5 hash from the content of the resource and appends it to the file name.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>For example: Assume we have a JavaScript file test.js inside the classpath:\/static\/ directory. The MD5 hash for test.js is 69ea0cf3b5941340f06ea65583193168.<\/p>\n<p>We can now send a request to:<\/p>\n<pre class=\" brush:bash\">\/javascript\/test-69ea0cf3b5941340f06ea65583193168.js<\/pre>\n<p>which will resolve to classpath:\/static\/test.js.<\/p>\n<p>Note that it is still possible to request the resource without the MD5 hash. So this request works too:<\/p>\n<pre class=\" brush:bash\">\/javascript\/test.js<\/pre>\n<p>An alternative VersionStrategy implementation is <a title=\"Spring FixedVersionStrategy API documentation\" href=\"http:\/\/docs.spring.io\/spring\/docs\/current\/javadoc-api\/org\/springframework\/web\/servlet\/resource\/FixedVersionStrategy.html\">FixedVersionStrategy<\/a>. FixedVersionStrategy uses a fixed version string that added as prefix to the resource path.<\/p>\n<p>For example:<\/p>\n<pre class=\" brush:bash\">\/v1.2.3\/javascript\/test.js<\/pre>\n<h2>Generating versioned URLs<\/h2>\n<p>Now we need to make sure the application generates resource URLs that contain the MD5 hash.<\/p>\n<p>One approach for this is to use a <a title=\"Spring ResourceUrlProvider API documentation\" href=\"http:\/\/docs.spring.io\/spring\/docs\/current\/javadoc-api\/org\/springframework\/web\/servlet\/resource\/ResourceUrlProvider.html\">ResourceUrlProvider<\/a>. With a ResourceUrlProvider a resource URL (e.g. \/javascript\/test.js) can be converted to a versioned URL (e.g. \/javascript\/test-69ea0cf3b5941340f06ea65583193168.js). A ResourceUrlProvider bean with the id mvcResourceUrlProvider is automatically declared with the MVC configuration.<\/p>\n<p>In case you are using Thymeleaf as template engine, you can access the ResourceUrlProvider bean directly from templates using the @bean syntax.<\/p>\n<p>For example:<\/p>\n<pre class=\" brush:xml\">&lt;script\u00a0type=\"application\/javascript\"\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0th:src=\"${@mvcResourceUrlProvider.getForLookupPath('\/javascript\/test.js')}\"&gt;\r\n&lt;\/script&gt;<\/pre>\n<p>If you are using a template engine which does not give you direct access to Spring beans, you can add the ResourceUrlProvider bean to the model attributes. Using a <a title=\"Spring ControllerAdvice API documentation\" href=\"http:\/\/docs.spring.io\/spring\/docs\/current\/javadoc-api\/org\/springframework\/web\/bind\/annotation\/ControllerAdvice.html\">ControllerAdvice<\/a>, this might look like this:<\/p>\n<pre class=\" brush:java\">@ControllerAdvice\r\npublic\u00a0class\u00a0ResourceUrlAdvice\u00a0{\r\n\r\n\u00a0\u00a0@Inject\r\n\u00a0\u00a0ResourceUrlProvider\u00a0resourceUrlProvider;\r\n\r\n\u00a0\u00a0@ModelAttribute(\"urls\")\r\n\u00a0\u00a0public\u00a0ResourceUrlProvider\u00a0urls()\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0return\u00a0this.resourceUrlProvider;\r\n\u00a0\u00a0}\r\n}<\/pre>\n<p>Inside the view we can then access the ResourceUrlProvider using the urls model attribute:<\/p>\n<pre class=\" brush:xml\">&lt;script\u00a0type=\"application\/javascript\"\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0th:src=\"${urls.getForLookupPath('\/javascript\/test.js')}\"&gt;\r\n&lt;\/script&gt;<\/pre>\n<p>This approach should work with all template engines that support method calls.<\/p>\n<p>An alternative approach to generate versioned URLs is the use of <a title=\"Spring ResourceUrlEncodingFilter API documentation\" href=\"http:\/\/docs.spring.io\/spring\/docs\/current\/javadoc-api\/org\/springframework\/web\/servlet\/resource\/ResourceUrlEncodingFilter.html\">ResourceUrlEncodingFilter<\/a>. This is a Servlet Filter that overrides the HttpServletResponse.encodeURL() method to generate versioned resource URLs.<\/p>\n<p>To make use of the ResourceUrlEncodingFilter we simply have to add an additional bean to our configuration class:<\/p>\n<pre class=\" brush:java\">@SpringBootApplication\r\npublic\u00a0class\u00a0MvcApplication\u00a0extends\u00a0WebMvcConfigurerAdapter\u00a0{\r\n\r\n\u00a0\u00a0@Override\r\n\u00a0\u00a0public\u00a0void\u00a0addResourceHandlers(ResourceHandlerRegistry\u00a0registry)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\/\/\u00a0same\u00a0as\u00a0before\u00a0..\r\n\u00a0\u00a0}\r\n\r\n\u00a0\u00a0@Bean\r\n\u00a0\u00a0public\u00a0ResourceUrlEncodingFilter\u00a0resourceUrlEncodingFilter()\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0return\u00a0new\u00a0ResourceUrlEncodingFilter();\r\n\u00a0\u00a0}\r\n\r\n\u00a0\u00a0...\r\n}<\/pre>\n<p>If the template engine you are using calls the response encodeURL() method, the version information will be automatically added to the URL. This will work in JSPs, Thymeleaf, FreeMarker and Velocity.<\/p>\n<p>For example: With Thymeleaf we can use the standard @{..} syntax to create URLs:<\/p>\n<pre class=\" brush:xml\">&lt;script\u00a0type=\"application\/javascript\"\u00a0th:src=\"@{\/javascript\/test.js}\"&gt;&lt;\/script&gt;<\/pre>\n<p>This will result in:<\/p>\n<pre class=\" brush:xml\">&lt;script\u00a0type=\"application\/javascript\"\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0src=\"\/javascript\/test-69ea0cf3b5941340f06ea65583193168.js\"&gt;\r\n&lt;\/script&gt;<\/pre>\n<h2>Summary<\/h2>\n<p>Adding version information to resource URLs is a common practice to maximize browser caching. With Spring we just have to define a VersionResourceResolver and a VersionStrategy to serve versioned URLs. The easiest way to generate versioned URLs inside template engines, is the use of an ResourceUrlEncodingFilter.<\/p>\n<p>If the standard VersionStrategy implementations do not match your requirements, you can create our own VersionStrategy implementation.<\/p>\n<ul>\n<li>You can find the full example source code on <a title=\"Example source code on GitHub\" href=\"https:\/\/github.com\/mscharhag\/blog-examples\/tree\/master\/spring-resource-versioning\">GitHub<\/a>.<\/li>\n<\/ul>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/www.mscharhag.com\/spring\/resource-versioning-with-spring-mvc\">Resource versioning with Spring MVC<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\/\">JCG partner<\/a> Michael Scharhag at the <a href=\"http:\/\/www.mscharhag.com\/\">mscharhag, Programming and Stuff<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>When serving static resources, it is common practice to append some kind of version information to the resource URL. This allows the browser to cache resources for an unlimited time. Whenever the content of the resource is changed, the version information in the URL is changed too. The updated URL forces the client browser to &hellip;<\/p>\n","protected":false},"author":514,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30,150],"class_list":["post-44154","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring","tag-spring-mvc"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Resource versioning with Spring MVC - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"When serving static resources, it is common practice to append some kind of version information to the resource URL. This allows the browser to cache\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Resource versioning with Spring MVC - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"When serving static resources, it is common practice to append some kind of version information to the resource URL. This allows the browser to cache\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-09-24T07:00:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Michael Scharhag\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/mscharhag\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Michael Scharhag\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html\"},\"author\":{\"name\":\"Michael Scharhag\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/0f0f81e875d40e3f820392e0ffce65d1\"},\"headline\":\"Resource versioning with Spring MVC\",\"datePublished\":\"2015-09-24T07:00:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html\"},\"wordCount\":628,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Spring\",\"Spring MVC\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html\",\"name\":\"Resource versioning with Spring MVC - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2015-09-24T07:00:54+00:00\",\"description\":\"When serving static resources, it is common practice to append some kind of version information to the resource URL. This allows the browser to cache\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/resource-versioning-with-spring-mvc.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Resource versioning with Spring MVC\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/0f0f81e875d40e3f820392e0ffce65d1\",\"name\":\"Michael Scharhag\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/52283459bfc820fb6a66704b3eccc771a1d8a63a0bdbbe1651bb5cb383a42148?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/52283459bfc820fb6a66704b3eccc771a1d8a63a0bdbbe1651bb5cb383a42148?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/52283459bfc820fb6a66704b3eccc771a1d8a63a0bdbbe1651bb5cb383a42148?s=96&d=mm&r=g\",\"caption\":\"Michael Scharhag\"},\"description\":\"Michael Scharhag is a Java Developer, Blogger and technology enthusiast. Particularly interested in Java related technologies including Java EE, Spring, Groovy and Grails.\",\"sameAs\":[\"http:\\\/\\\/www.mscharhag.com\\\/\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/mscharhag\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/michael-scharhag\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Resource versioning with Spring MVC - Java Code Geeks","description":"When serving static resources, it is common practice to append some kind of version information to the resource URL. This allows the browser to cache","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html","og_locale":"en_US","og_type":"article","og_title":"Resource versioning with Spring MVC - Java Code Geeks","og_description":"When serving static resources, it is common practice to append some kind of version information to the resource URL. This allows the browser to cache","og_url":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2015-09-24T07:00:54+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Michael Scharhag","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/mscharhag","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Michael Scharhag","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html"},"author":{"name":"Michael Scharhag","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/0f0f81e875d40e3f820392e0ffce65d1"},"headline":"Resource versioning with Spring MVC","datePublished":"2015-09-24T07:00:54+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html"},"wordCount":628,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Spring","Spring MVC"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html","url":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html","name":"Resource versioning with Spring MVC - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2015-09-24T07:00:54+00:00","description":"When serving static resources, it is common practice to append some kind of version information to the resource URL. This allows the browser to cache","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/resource-versioning-with-spring-mvc.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Resource versioning with Spring MVC"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/0f0f81e875d40e3f820392e0ffce65d1","name":"Michael Scharhag","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/52283459bfc820fb6a66704b3eccc771a1d8a63a0bdbbe1651bb5cb383a42148?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/52283459bfc820fb6a66704b3eccc771a1d8a63a0bdbbe1651bb5cb383a42148?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/52283459bfc820fb6a66704b3eccc771a1d8a63a0bdbbe1651bb5cb383a42148?s=96&d=mm&r=g","caption":"Michael Scharhag"},"description":"Michael Scharhag is a Java Developer, Blogger and technology enthusiast. Particularly interested in Java related technologies including Java EE, Spring, Groovy and Grails.","sameAs":["http:\/\/www.mscharhag.com\/","https:\/\/x.com\/https:\/\/twitter.com\/mscharhag"],"url":"https:\/\/www.javacodegeeks.com\/author\/michael-scharhag"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/44154","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/514"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=44154"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/44154\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=44154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=44154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=44154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}