BAEL3771 Cache Headers in Spring MVC (#8682)
* BAEL3771: Cache Headers in Spring MVC * BEAL3771: Cache Headers in Spring MVC * BEAL3771: Cache Headers in Spring MVC
This commit is contained in:
parent
4869ddbc3e
commit
70853770dd
2
pom.xml
2
pom.xml
|
@ -692,6 +692,7 @@
|
|||
<module>spring-mvc-forms-jsp</module>
|
||||
<module>spring-mvc-forms-thymeleaf</module>
|
||||
<module>spring-mvc-java</module>
|
||||
<module>spring-mvc-java-2</module>
|
||||
<module>spring-mvc-kotlin</module>
|
||||
|
||||
<module>spring-mvc-velocity</module>
|
||||
|
@ -1193,6 +1194,7 @@
|
|||
<module>spring-mvc-forms-jsp</module>
|
||||
<module>spring-mvc-forms-thymeleaf</module>
|
||||
<module>spring-mvc-java</module>
|
||||
<module>spring-mvc-java-2</module>
|
||||
<module>spring-mvc-kotlin</module>
|
||||
|
||||
<module>spring-mvc-velocity</module>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
*.class
|
||||
|
||||
#folders#
|
||||
/target
|
||||
/neoDb*
|
||||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-mvc-java-2</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>spring-mvc-java-2</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${spring.mvc.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<javax.version>4.0.1</javax.version>
|
||||
<spring.mvc.version>5.2.2.RELEASE</spring.mvc.version>
|
||||
</properties>
|
||||
|
||||
|
||||
|
||||
</project>
|
55
spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheControlController.java
vendored
Normal file
55
spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheControlController.java
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
package com.baeldung.cache;
|
||||
|
||||
import org.springframework.http.CacheControl;
|
||||
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.RequestMethod;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Controller
|
||||
public class CacheControlController {
|
||||
|
||||
@RequestMapping(value = "/hello/{name}", method = RequestMethod.GET)
|
||||
public ResponseEntity<String> helloWorld(@PathVariable String name) {
|
||||
CacheControl cacheControl = CacheControl.maxAge(60, TimeUnit.SECONDS)
|
||||
.noTransform()
|
||||
.mustRevalidate();
|
||||
return ResponseEntity.ok()
|
||||
.cacheControl(cacheControl)
|
||||
.body("Hello " + name);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/home/{name}", method = RequestMethod.GET)
|
||||
public String home(@PathVariable String name, final HttpServletResponse response) {
|
||||
response.addHeader("Cache-Control", "max-age=60, must-revalidate, no-transform");
|
||||
return "home";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/cache/{name}", method = RequestMethod.GET)
|
||||
public ResponseEntity<String> intercept(@PathVariable String name) {
|
||||
return ResponseEntity.ok().body("Hello " + name);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/validate/{name}", method = RequestMethod.GET)
|
||||
public ResponseEntity<String> validate(@PathVariable String name, WebRequest request) {
|
||||
|
||||
ZoneId zoneId = ZoneId.of("GMT");
|
||||
long lastModifiedTimestamp = LocalDateTime.of(2020, 02, 4, 19, 57, 45)
|
||||
.atZone(zoneId).toInstant().toEpochMilli();
|
||||
|
||||
if (request.checkNotModified(lastModifiedTimestamp)) {
|
||||
return ResponseEntity.status(304).build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok().body("Hello " + name);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.cache;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.mvc.WebContentInterceptor;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
@ComponentScan(basePackages = {"com.baeldung.cache"})
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addViewControllers(final ViewControllerRegistry registry) {
|
||||
registry.addViewController("/").setViewName("index");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/")
|
||||
.setCacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS)
|
||||
.noTransform()
|
||||
.mustRevalidate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||
interceptor.addCacheMapping(CacheControl.maxAge(60, TimeUnit.SECONDS)
|
||||
.noTransform()
|
||||
.mustRevalidate(), "/cache/*");
|
||||
registry.addInterceptor(interceptor);
|
||||
}
|
||||
}
|
80
spring-mvc-java-2/src/test/java/com/baeldung/cache/CacheControlControllerIntegrationTest.java
vendored
Normal file
80
spring-mvc-java-2/src/test/java/com/baeldung/cache/CacheControlControllerIntegrationTest.java
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
package com.baeldung.cache;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.http.HttpHeaders.IF_UNMODIFIED_SINCE;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(classes = {WebConfig.class, WebConfig.class})
|
||||
public class CacheControlControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext wac;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@BeforeEach
|
||||
void setup() throws Exception {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenResponseBody_thenReturnCacheHeader() throws Exception {
|
||||
this.mockMvc.perform(MockMvcRequestBuilders.get("/hello/baeldung"))
|
||||
.andDo(MockMvcResultHandlers.print())
|
||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.header().string("Cache-Control","max-age=60, must-revalidate, no-transform"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenViewName_thenReturnCacheHeader() throws Exception {
|
||||
this.mockMvc.perform(MockMvcRequestBuilders.get("/home/baeldung"))
|
||||
.andDo(MockMvcResultHandlers.print())
|
||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.header().string("Cache-Control","max-age=60, must-revalidate, no-transform"))
|
||||
.andExpect(MockMvcResultMatchers.view().name("home"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenStaticResources_thenReturnCacheHeader() throws Exception {
|
||||
this.mockMvc.perform(MockMvcRequestBuilders.get("/resources/hello.css"))
|
||||
.andDo(MockMvcResultHandlers.print())
|
||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.header().string("Cache-Control","max-age=60, must-revalidate, no-transform"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenInterceptor_thenReturnCacheHeader() throws Exception {
|
||||
this.mockMvc.perform(MockMvcRequestBuilders.get("/cache/baeldung"))
|
||||
.andDo(MockMvcResultHandlers.print())
|
||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.header().string("Cache-Control","max-age=60, must-revalidate, no-transform"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenValidate_thenReturnCacheHeader() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(IF_UNMODIFIED_SINCE, "Tue, 04 Feb 2020 19:57:25 GMT");
|
||||
this.mockMvc.perform(MockMvcRequestBuilders.get("/validate/baeldung").headers(headers))
|
||||
.andDo(MockMvcResultHandlers.print())
|
||||
.andExpect(MockMvcResultMatchers.status().is(304));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue