Mastering Spring MVC Configuration: In‑Depth Guide to WebMvcConfigurer
This guide explains how the WebMvcConfigurer callback interface lets developers extend Spring MVC behavior without disabling Spring Boot’s auto‑configuration, covering the full request lifecycle, common customizations such as interceptors, CORS, message converters, static resources, async support, and production‑grade pitfalls.
Introduction
In Spring MVC development, configuration is essential. WebMvcConfigurer is a Java‑based callback interface that allows developers to customize MVC behavior while preserving Spring Boot’s automatic configuration.
Quick Start
@Configuration
public class WebConfig implements WebMvcConfigurer {
}Spring Boot automatically scans and applies this configuration.
Spring MVC Request Processing Flow
The request passes through the following components:
DispatcherServlet – core dispatcher
HandlerMapping – maps URL to a controller
HandlerInterceptor.preHandle
Controller
HandlerInterceptor.postHandle
ViewResolver / HttpMessageConverter – renders the response
HandlerInterceptor.afterCompletion
Where WebMvcConfigurer Fits
WebMvcConfigureris the extension entry for MVC components. Key methods and the components they affect include:
addInterceptors → HandlerInterceptor
addResourceHandlers → ResourceHttpRequestHandler
addFormatters → DataBinder
extendMessageConverters → HttpMessageConverter
configurePathMatch → HandlerMapping
configureAsyncSupport → AsyncRequest
Common Configurations
1. Interceptor
Used for login validation, permission checks, request logging, rate limiting, etc.
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login", "/css/**", "/js/**");
}
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("before controller");
return true;
}
}2. View Controllers
Map URLs directly to views without a controller.
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
registry.addViewController("/login").setViewName("login");
}3. Static Resource Handling
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/", "file:/data/static/")
.setCachePeriod(3600)
.resourceChain(true);
}4. CORS Configuration
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
// Or use the annotation
@CrossOrigin5. HttpMessageConverter
Converts between Java objects and HTTP bodies (JSON, XML, String). To add a custom converter without losing defaults:
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new MyCustomConverter());
}Do not use configureMessageConverters because it replaces the default converters.
6. Content Negotiation
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorParameter(true)
.parameterName("format")
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("json", MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML);
}
// Request example: /api/user?format=json7. Formatter & Converter
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToEnumConverter());
registry.addFormatter(new DateFormatter("yyyy-MM-dd"));
}
// Example conversions: String → Date, String → Enum8. Path Matching
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseTrailingSlashMatch(true);
configurer.setUseSuffixPatternMatch(false);
}9. Async Request Support
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setDefaultTimeout(5000);
configurer.setTaskExecutor(mvcExecutor());
}Spring Boot Auto‑Configuration Mechanism
Spring Boot registers WebMvcAutoConfiguration, which delegates to DelegatingWebMvcConfiguration. That class collects all WebMvcConfigurer beans via WebMvcConfigurerComposite and applies them in order.
Interceptor vs Filter vs AOP
Filter – Servlet layer, used for encoding, CORS.
Interceptor – Spring MVC layer, used for login checks.
AOP – Spring layer, used for logging, transactions.
Execution order: Filter → Interceptor.preHandle → Controller → Interceptor.postHandle → Interceptor.afterCompletion → Filter.
Spring Boot 2.6 PathPattern Change
From Spring Boot 2.6 the default path matcher switches from AntPathMatcher to PathPatternParser, offering higher performance. To keep the old behavior set spring.mvc.pathmatch.matching-strategy=ant_path_matcher.
Production‑Grade Template
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/login", "/error", "/static/**", "/swagger/**");
}
@Bean
public HandlerInterceptor authInterceptor() {
return new AuthInterceptor();
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("*")
.allowedMethods("*")
.maxAge(3600);
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
}
}
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new DateFormatter("yyyy-MM-dd"));
}
}Common Pitfalls
1. Using @EnableWebMvc
Disables Spring Boot’s MVC auto‑configuration, causing static resources to return 404. Solution: avoid @EnableWebMvc.
2. Overriding Message Converters
Implementing configureMessageConverters removes the default converters. Use extendMessageConverters instead.
3. Interceptor Capturing Static Resources
Static assets may fail to load. Exclude them with excludePathPatterns("/static/**").
Spring MVC vs WebFlux
Model: Servlet (MVC) vs Reactive (WebFlux)
IO: Blocking vs Non‑blocking
Server: Tomcat vs Netty
Concurrency: Thread pool vs EventLoop
Conclusion
WebMvcConfigureris one of the core extension points of Spring MVC. It enables developers to customize MVC behavior—interceptors, CORS, message converters, static resources, path matching, content negotiation, formatters, async handling—without breaking Spring Boot’s auto‑configuration, and helps solve common production issues.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Cloud Architecture
Focuses on cloud‑native and distributed architecture engineering, sharing practical solutions and lessons learned. Covers microservice governance, Kubernetes, observability, and stability engineering to help your systems run stable, fast, and cost‑effectively.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
