To bootstrap a Spring MVC application, you have to enable Spring built-in DisptachServlet.
Serlvet 3.0 provides a new feature ServletInitializer to configure web applciation without web.xml.
Spring has its WebApplicationInitializer interface, there are a few classes implement this interface, AbstractAnnotationConfigDispatcherServletInitializer includes configuration of Spring Dispatch Servlet, and leaves some room to customize DispatchServlet.
Declare a AbstractAnnotationConfigDispatcherServletInitializer bean.
getRootConfigClasses specifies the configuration classes should be loaded for the Spring infrastrucuture.
getServletConfigClasses specifies the configurations depend on Servlet specification, esp, web mvc related configurations.
getServletMappings is the Spring DispatchServlet mapping URL pattern.
getServletFilters are those Web Filters will be applied on the Spring DispatchServlet.
Spring MVC DispatchServlet is configured in the super classes, explore the details if you are interested in it.
In getServletConfigClasses, we specify a WebConfig will be loaded, which is responsible for configuring Spring MVC in details, including resource handling, view, view resolvers etc.
A classic WebConfig looks like.
public class WebConfig extends WebMvcConfigurerAdapter {
}
Generally, WebMvcConfigurerAdapter is the extension point left for users to use for customizing MVC configurations.
Spring Data project provides a SpringDataWebConfiguration which is a subclass of WebMvcConfigurerAdapter and adds pagination, sort, and domain object conversion support. Open the source code of SpringDataWebConfiguration and research yourself.
The following is the full source code of WebConfig.
@Configuration
@EnableWebMvc
@ComponentScan(
basePackageClasses = {Constants.class},
useDefaultFilters = false,
includeFilters = {
@Filter(
type = FilterType.ANNOTATION,
value = {
Controller.class,
RestController.class,
ControllerAdvice.class
}
)
}
)
public class WebConfig extends SpringDataWebConfiguration {
private static final Logger logger = LoggerFactory.getLogger(WebConfig.class);
@Inject
private ObjectMapper objectMapper;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/swagger-ui.html")
.addResourceLocations("classpath:META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:META-INF/resources/webjars/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
}
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
exceptionResolvers.add(exceptionHandlerExceptionResolver());
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorParameter(false);
configurer.favorPathExtension(false);
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
List<HttpMessageConverter<?>> messageConverters = messageConverters();
converters.addAll(messageConverters);
}
@Bean
public ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver() {
ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new ExceptionHandlerExceptionResolver();
exceptionHandlerExceptionResolver.setMessageConverters(messageConverters());
return exceptionHandlerExceptionResolver;
}
private List<HttpMessageConverter<?>> messageConverters() {
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
MappingJackson2HttpMessageConverter jackson2Converter = new MappingJackson2HttpMessageConverter();
jackson2Converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON));
jackson2Converter.setObjectMapper(objectMapper);
messageConverters.add(jackson2Converter);
return messageConverters;
}
}
@EnableWebMvc tells Spring to enable Spring MVC.
@ComponentScan uses a filter to select Spring MVC related classes to be activated.
addResourceHandlers configure how to handle static resources.
addViewControllers leave places to configure view resolver to render specific views.
configureMessageConverters configure HttpMessageConverter will be used for serialization and deserialization.
I would like use application/json as default content type, and uses Jackson to serialize and deserialize messages.
Configure a Jackson ObjectMapper as you need.
@Configuration
public class Jackson2ObjectMapperConfig {
@Bean
public ObjectMapper objectMapper() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.serializationInclusion(Include.NON_EMPTY);
builder.featuresToDisable(
// SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES,
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
builder.featuresToEnable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
return builder.build();
}
}
Jackson2ObjectMapperBuilder provides fluent APIs to configure which features will be enabled or disabled for serialization and deserialization. For the complete configurable options, check the javadocs of SerializationFeature and DeserializationFeature.