Merge branch 'master' of https://github.com/dev-chirag/tutorials
This commit is contained in:
commit
bfba3e457a
|
@ -2,6 +2,7 @@ package com.baeldung.spring.web.config;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
@ -9,15 +10,19 @@ import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Description;
|
import org.springframework.context.annotation.Description;
|
||||||
import org.springframework.context.support.ResourceBundleMessageSource;
|
import org.springframework.context.support.ResourceBundleMessageSource;
|
||||||
|
import org.springframework.http.CacheControl;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.web.servlet.ViewResolver;
|
import org.springframework.web.servlet.ViewResolver;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
|
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
|
||||||
|
import org.springframework.web.servlet.mvc.WebContentInterceptor;
|
||||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||||
import org.springframework.web.servlet.view.JstlView;
|
import org.springframework.web.servlet.view.JstlView;
|
||||||
import org.springframework.web.util.UrlPathHelper;
|
import org.springframework.web.util.UrlPathHelper;
|
||||||
|
@ -30,14 +35,14 @@ import com.baeldung.excel.ExcelPOIHelper;
|
||||||
|
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
@Configuration
|
@Configuration
|
||||||
@ComponentScan(basePackages = { "com.baeldung.web.controller" })
|
@ComponentScan(basePackages = {"com.baeldung.web.controller"})
|
||||||
public class WebConfig implements WebMvcConfigurer {
|
public class WebConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addViewControllers(final ViewControllerRegistry registry) {
|
public void addViewControllers(final ViewControllerRegistry registry) {
|
||||||
registry.addViewController("/").setViewName("index");
|
registry.addViewController("/").setViewName("index");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ViewResolver thymeleafViewResolver() {
|
public ViewResolver thymeleafViewResolver() {
|
||||||
final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
|
final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
|
||||||
|
@ -84,7 +89,10 @@ public class WebConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
|
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
|
||||||
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
|
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/")
|
||||||
|
.setCacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS)
|
||||||
|
.noTransform()
|
||||||
|
.mustRevalidate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -121,4 +129,13 @@ public class WebConfig implements WebMvcConfigurer {
|
||||||
public ExcelPOIHelper excelPOIHelper() {
|
public ExcelPOIHelper excelPOIHelper() {
|
||||||
return new ExcelPOIHelper();
|
return new ExcelPOIHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||||
|
interceptor.addCacheMapping(CacheControl.maxAge(60, TimeUnit.SECONDS)
|
||||||
|
.noTransform()
|
||||||
|
.mustRevalidate(), "/cache/*");
|
||||||
|
registry.addInterceptor(interceptor);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.baeldung.web.controller;
|
||||||
|
|
||||||
|
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,84 @@
|
||||||
|
package com.baeldung.web.controller;
|
||||||
|
|
||||||
|
import com.baeldung.spring.web.config.WebConfig;
|
||||||
|
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 java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
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