Configure Spring WebMVC

Firstly add Spring WebMvc related dependenices into pom.xml.

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
</dependency>

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.

@Order(0)
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
       return new Class[] {
               AppConfig.class, //
               DataSourceConfig.class, //            
               JpaConfig.class, //
               DataJpaConfig.class,//
               SecurityConfig.class,//   
               Jackson2ObjectMapperConfig.class,//
               MessageSourceConfig.class
       };
   }

   @Override
   protected Class<?>[] getServletConfigClasses() {
       return new Class[] {
           WebConfig.class, //
           SwaggerConfig.class //
       };
   }

   @Override
   protected String[] getServletMappings() {
       return new String[] { "/" };
   }

   @Override
   protected Filter[] getServletFilters() {
       CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
       encodingFilter.setEncoding("UTF-8");
       encodingFilter.setForceEncoding(true);

       return new Filter[] { encodingFilter };
   }

}

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.

  • configureHandlerExceptionResolvers specifies exception handling stretagy.

  • 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.

Last updated