Package org.springframework.web.servlet.config.annotation

Source Code of org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport$NoOpValidator

/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.web.servlet.config.annotation;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.xml.transform.Source;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter;
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ClassUtils;
import org.springframework.util.PathMatcher;
import org.springframework.validation.Errors;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.method.support.CompositeUriComponentsContributor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
import org.springframework.web.servlet.resource.ResourceUrlProvider;
import org.springframework.web.servlet.resource.ResourceUrlProviderExposingInterceptor;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.ViewResolverComposite;
import org.springframework.web.util.UrlPathHelper;

/**
* This is the main class providing the configuration behind the MVC Java config.
* It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an
* application {@link Configuration @Configuration} class. An alternative more
* advanced option is to extend directly from this class and override methods as
* necessary remembering to add {@link Configuration @Configuration} to the
* subclass and {@link Bean @Bean} to overridden {@link Bean @Bean} methods.
* For more details see the Javadoc of {@link EnableWebMvc @EnableWebMvc}.
*
* <p>This class registers the following {@link HandlerMapping}s:</p>
* <ul>
* <li>{@link RequestMappingHandlerMapping}
* ordered at 0 for mapping requests to annotated controller methods.
* <li>{@link HandlerMapping}
* ordered at 1 to map URL paths directly to view names.
* <li>{@link BeanNameUrlHandlerMapping}
* ordered at 2 to map URL paths to controller bean names.
* <li>{@link HandlerMapping}
* ordered at {@code Integer.MAX_VALUE-1} to serve static resource requests.
* <li>{@link HandlerMapping}
* ordered at {@code Integer.MAX_VALUE} to forward requests to the default servlet.
* </ul>
*
* <p>Registers these {@link HandlerAdapter}s:
* <ul>
* <li>{@link RequestMappingHandlerAdapter}
* for processing requests with annotated controller methods.
* <li>{@link HttpRequestHandlerAdapter}
* for processing requests with {@link HttpRequestHandler}s.
* <li>{@link SimpleControllerHandlerAdapter}
* for processing requests with interface-based {@link Controller}s.
* </ul>
*
* <p>Registers a {@link HandlerExceptionResolverComposite} with this chain of
* exception resolvers:
* <ul>
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions
* through @{@link ExceptionHandler} methods.
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
* with @{@link ResponseStatus}.
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
* exception types
* </ul>
*
* <p>Registers an {@link AntPathMatcher} and a {@link UrlPathHelper}
* to be used by:
* <ul>
* <li>the {@link RequestMappingHandlerMapping},
* <li>the {@link HandlerMapping} for ViewControllers
* <li>and the {@link HandlerMapping} for serving resources
* </ul>
* Note that those beans can be configured with a {@link PathMatchConfigurer}.
*
* <p>Both the {@link RequestMappingHandlerAdapter} and the
* {@link ExceptionHandlerExceptionResolver} are configured with default
* instances of the following by default:
* <ul>
* <li>a {@link ContentNegotiationManager}
* <li>a {@link DefaultFormattingConversionService}
* <li>a {@link org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean}
* if a JSR-303 implementation is available on the classpath
* <li>a range of {@link HttpMessageConverter}s depending on the third-party
* libraries available on the classpath.
* </ul>
*
* @author Rossen Stoyanchev
* @author Brian Clozel
* @author Sebastien Deleuze
* @since 3.1
* @see EnableWebMvc
* @see WebMvcConfigurer
* @see WebMvcConfigurerAdapter
*/
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {

  private static boolean romePresent =
      ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", WebMvcConfigurationSupport.class.getClassLoader());

  private static final boolean jaxb2Present =
      ClassUtils.isPresent("javax.xml.bind.Binder", WebMvcConfigurationSupport.class.getClassLoader());

  private static final boolean jackson2Present =
      ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", WebMvcConfigurationSupport.class.getClassLoader()) &&
          ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", WebMvcConfigurationSupport.class.getClassLoader());

  private static final boolean jackson2XmlPresent =
      ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", WebMvcConfigurationSupport.class.getClassLoader());

  private static final boolean gsonPresent =
      ClassUtils.isPresent("com.google.gson.Gson", WebMvcConfigurationSupport.class.getClassLoader());


  private ApplicationContext applicationContext;

  private ServletContext servletContext;

  private List<Object> interceptors;

  private PathMatchConfigurer pathMatchConfigurer;

  private ContentNegotiationManager contentNegotiationManager;

  private List<HttpMessageConverter<?>> messageConverters;


  /**
   * Set the Spring {@link ApplicationContext}, e.g. for resource loading.
   */
  @Override
  public void setApplicationContext(ApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
  }

  /**
   * Set the {@link javax.servlet.ServletContext}, e.g. for resource handling,
   * looking up file extensions, etc.
   */
  @Override
  public void setServletContext(ServletContext servletContext) {
    this.servletContext = servletContext;
  }


  /**
   * Return a {@link RequestMappingHandlerMapping} ordered at 0 for mapping
   * requests to annotated controllers.
   */
  @Bean
  public RequestMappingHandlerMapping requestMappingHandlerMapping() {
    RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping();
    handlerMapping.setOrder(0);
    handlerMapping.setInterceptors(getInterceptors());
    handlerMapping.setContentNegotiationManager(mvcContentNegotiationManager());

    PathMatchConfigurer configurer = getPathMatchConfigurer();
    if (configurer.isUseSuffixPatternMatch() != null) {
      handlerMapping.setUseSuffixPatternMatch(configurer.isUseSuffixPatternMatch());
    }
    if (configurer.isUseRegisteredSuffixPatternMatch() != null) {
      handlerMapping.setUseRegisteredSuffixPatternMatch(configurer.isUseRegisteredSuffixPatternMatch());
    }
    if (configurer.isUseTrailingSlashMatch() != null) {
      handlerMapping.setUseTrailingSlashMatch(configurer.isUseTrailingSlashMatch());
    }
    if (configurer.getPathMatcher() != null) {
      handlerMapping.setPathMatcher(configurer.getPathMatcher());
    }
    if (configurer.getUrlPathHelper() != null) {
      handlerMapping.setUrlPathHelper(configurer.getUrlPathHelper());
    }

    return handlerMapping;
  }

  /**
   * Provide access to the shared handler interceptors used to configure
   * {@link HandlerMapping} instances with. This method cannot be overridden,
   * use {@link #addInterceptors(InterceptorRegistry)} instead.
   */
  protected final Object[] getInterceptors() {
    if (this.interceptors == null) {
      InterceptorRegistry registry = new InterceptorRegistry();
      addInterceptors(registry);
      registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService()));
      registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
      this.interceptors = registry.getInterceptors();
    }
    return this.interceptors.toArray();
  }

  /**
   * Override this method to add Spring MVC interceptors for
   * pre- and post-processing of controller invocation.
   * @see InterceptorRegistry
   */
  protected void addInterceptors(InterceptorRegistry registry) {
  }

  /**
   * Callback for building the {@link PathMatchConfigurer}.
   * Delegates to {@link #configurePathMatch}.
   * @since 4.1
   */
  protected PathMatchConfigurer getPathMatchConfigurer() {
    if (this.pathMatchConfigurer == null) {
      this.pathMatchConfigurer = new PathMatchConfigurer();
      configurePathMatch(this.pathMatchConfigurer);
    }
    return this.pathMatchConfigurer;
  }

  /**
   * Override this method to configure path matching options.
   * @see PathMatchConfigurer
   * @since 4.0.3
   */
  public void configurePathMatch(PathMatchConfigurer configurer) {
  }

  /**
   * Return a {@link ContentNegotiationManager} instance to use to determine
   * requested {@linkplain MediaType media types} in a given request.
   */
  @Bean
  public ContentNegotiationManager mvcContentNegotiationManager() {
    if (this.contentNegotiationManager == null) {
      ContentNegotiationConfigurer configurer = new ContentNegotiationConfigurer(this.servletContext);
      configurer.mediaTypes(getDefaultMediaTypes());
      configureContentNegotiation(configurer);
      try {
        this.contentNegotiationManager = configurer.getContentNegotiationManager();
      }
      catch (Exception ex) {
        throw new BeanInitializationException("Could not create ContentNegotiationManager", ex);
      }
    }
    return this.contentNegotiationManager;
  }

  protected Map<String, MediaType> getDefaultMediaTypes() {
    Map<String, MediaType> map = new HashMap<String, MediaType>();
    if (romePresent) {
      map.put("atom", MediaType.APPLICATION_ATOM_XML);
      map.put("rss", MediaType.valueOf("application/rss+xml"));
    }
    if (jaxb2Present || jackson2XmlPresent) {
      map.put("xml", MediaType.APPLICATION_XML);
    }
    if (jackson2Present || gsonPresent) {
      map.put("json", MediaType.APPLICATION_JSON);
    }
    return map;
  }

  /**
   * Override this method to configure content negotiation.
   * @see DefaultServletHandlerConfigurer
   */
  protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
  }

  /**
   * Return a handler mapping ordered at 1 to map URL paths directly to
   * view names. To configure view controllers, override
   * {@link #addViewControllers}.
   */
  @Bean
  public HandlerMapping viewControllerHandlerMapping() {
    ViewControllerRegistry registry = new ViewControllerRegistry();
    addViewControllers(registry);

    AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
    handlerMapping = (handlerMapping != null ? handlerMapping : new EmptyHandlerMapping());
    handlerMapping.setPathMatcher(mvcPathMatcher());
    handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
    handlerMapping.setInterceptors(getInterceptors());
    return handlerMapping;
  }

  /**
   * Override this method to add view controllers.
   * @see ViewControllerRegistry
   */
  protected void addViewControllers(ViewControllerRegistry registry) {
  }

  /**
   * Return a {@link BeanNameUrlHandlerMapping} ordered at 2 to map URL
   * paths to controller bean names.
   */
  @Bean
  public BeanNameUrlHandlerMapping beanNameHandlerMapping() {
    BeanNameUrlHandlerMapping mapping = new BeanNameUrlHandlerMapping();
    mapping.setOrder(2);
    mapping.setInterceptors(getInterceptors());
    return mapping;
  }

  /**
   * Return a handler mapping ordered at Integer.MAX_VALUE-1 with mapped
   * resource handlers. To configure resource handling, override
   * {@link #addResourceHandlers}.
   */
  @Bean
  public HandlerMapping resourceHandlerMapping() {
    ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext, this.servletContext);
    addResourceHandlers(registry);

    AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
    if (handlerMapping != null) {
      handlerMapping.setPathMatcher(mvcPathMatcher());
      handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
      handlerMapping.setInterceptors(new HandlerInterceptor[] {
          new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider())});
    }
    else {
      handlerMapping = new EmptyHandlerMapping();
    }
    return handlerMapping;
  }

  /**
   * Override this method to add resource handlers for serving static resources.
   * @see ResourceHandlerRegistry
   */
  protected void addResourceHandlers(ResourceHandlerRegistry registry) {
  }

  @Bean
  public ResourceUrlProvider mvcResourceUrlProvider() {
    ResourceUrlProvider urlProvider = new ResourceUrlProvider();
    UrlPathHelper pathHelper = getPathMatchConfigurer().getUrlPathHelper();
    if (pathHelper != null) {
      urlProvider.setUrlPathHelper(pathHelper);
    }
    PathMatcher pathMatcher = getPathMatchConfigurer().getPathMatcher();
    if (pathMatcher != null) {
      urlProvider.setPathMatcher(pathMatcher);
    }
    return urlProvider;
  }

  /**
   * Return a handler mapping ordered at Integer.MAX_VALUE with a mapped
   * default servlet handler. To configure "default" Servlet handling,
   * override {@link #configureDefaultServletHandling}.
   */
  @Bean
  public HandlerMapping defaultServletHandlerMapping() {
    DefaultServletHandlerConfigurer configurer = new DefaultServletHandlerConfigurer(servletContext);
    configureDefaultServletHandling(configurer);
    AbstractHandlerMapping handlerMapping = configurer.getHandlerMapping();
    handlerMapping = handlerMapping != null ? handlerMapping : new EmptyHandlerMapping();
    return handlerMapping;
  }

  /**
   * Override this method to configure "default" Servlet handling.
   * @see DefaultServletHandlerConfigurer
   */
  protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
  }

  /**
   * Returns a {@link RequestMappingHandlerAdapter} for processing requests
   * through annotated controller methods. Consider overriding one of these
   * other more fine-grained methods:
   * <ul>
   * <li>{@link #addArgumentResolvers} for adding custom argument resolvers.
   * <li>{@link #addReturnValueHandlers} for adding custom return value handlers.
   * <li>{@link #configureMessageConverters} for adding custom message converters.
   * </ul>
   */
  @Bean
  public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
    List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
    addArgumentResolvers(argumentResolvers);

    List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
    addReturnValueHandlers(returnValueHandlers);

    RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
    adapter.setContentNegotiationManager(mvcContentNegotiationManager());
    adapter.setMessageConverters(getMessageConverters());
    adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer());
    adapter.setCustomArgumentResolvers(argumentResolvers);
    adapter.setCustomReturnValueHandlers(returnValueHandlers);

    if (jackson2Present) {
      List<ResponseBodyAdvice<?>> interceptors = new ArrayList<ResponseBodyAdvice<?>>();
      interceptors.add(new JsonViewResponseBodyAdvice());
      adapter.setResponseBodyAdvice(interceptors);
    }

    AsyncSupportConfigurer configurer = new AsyncSupportConfigurer();
    configureAsyncSupport(configurer);

    if (configurer.getTaskExecutor() != null) {
      adapter.setTaskExecutor(configurer.getTaskExecutor());
    }
    if (configurer.getTimeout() != null) {
      adapter.setAsyncRequestTimeout(configurer.getTimeout());
    }
    adapter.setCallableInterceptors(configurer.getCallableInterceptors());
    adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());

    return adapter;
  }

  /**
   * Return the {@link ConfigurableWebBindingInitializer} to use for
   * initializing all {@link WebDataBinder} instances.
   */
  protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
    ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
    initializer.setConversionService(mvcConversionService());
    initializer.setValidator(mvcValidator());
    initializer.setMessageCodesResolver(getMessageCodesResolver());
    return initializer;
  }

  /**
   * Return a {@link FormattingConversionService} for use with annotated
   * controller methods and the {@code spring:eval} JSP tag.
   * Also see {@link #addFormatters} as an alternative to overriding this method.
   */
  @Bean
  public FormattingConversionService mvcConversionService() {
    FormattingConversionService conversionService = new DefaultFormattingConversionService();
    addFormatters(conversionService);
    return conversionService;
  }

  /**
   * Return a global {@link Validator} instance for example for validating
   * {@code @ModelAttribute} and {@code @RequestBody} method arguments.
   * Delegates to {@link #getValidator()} first and if that returns {@code null}
   * checks the classpath for the presence of a JSR-303 implementations
   * before creating a {@code OptionalValidatorFactoryBean}.If a JSR-303
   * implementation is not available, a no-op {@link Validator} is returned.
   */
  @Bean
  public Validator mvcValidator() {
    Validator validator = getValidator();
    if (validator == null) {
      if (ClassUtils.isPresent("javax.validation.Validator", getClass().getClassLoader())) {
        Class<?> clazz;
        try {
          String className = "org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean";
          clazz = ClassUtils.forName(className, WebMvcConfigurationSupport.class.getClassLoader());
        }
        catch (ClassNotFoundException ex) {
          throw new BeanInitializationException("Could not find default validator class", ex);
        }
        catch (LinkageError ex) {
          throw new BeanInitializationException("Could not load default validator class", ex);
        }
        validator = (Validator) BeanUtils.instantiate(clazz);
      }
      else {
        validator = new NoOpValidator();
      }
    }
    return validator;
  }

  /**
   * Return a global {@link PathMatcher} instance for path matching
   * patterns in {@link HandlerMapping}s.
   * This instance can be configured using the {@link PathMatchConfigurer}
   * in {@link #configurePathMatch(PathMatchConfigurer)}.
   * @since 4.1
   */
  @Bean
  public PathMatcher mvcPathMatcher() {
    if (getPathMatchConfigurer().getPathMatcher() != null) {
      return getPathMatchConfigurer().getPathMatcher();
    }
    else {
      return new AntPathMatcher();
    }
  }

  /**
   * Return a global {@link UrlPathHelper} instance for path matching
   * patterns in {@link HandlerMapping}s.
   * This instance can be configured using the {@link PathMatchConfigurer}
   * in {@link #configurePathMatch(PathMatchConfigurer)}.
   * @since 4.1
   */
  @Bean
  public UrlPathHelper mvcUrlPathHelper() {
    if (getPathMatchConfigurer().getUrlPathHelper() != null) {
      return getPathMatchConfigurer().getUrlPathHelper();
    }
    else {
      return new UrlPathHelper();
    }
  }

  /**
   * Override this method to provide a custom {@link Validator}.
   */
  protected Validator getValidator() {
    return null;
  }

  /**
   * Override this method to provide a custom {@link MessageCodesResolver}.
   */
  protected MessageCodesResolver getMessageCodesResolver() {
    return null;
  }

  /**
   * Add custom {@link HandlerMethodArgumentResolver}s to use in addition to
   * the ones registered by default.
   * <p>Custom argument resolvers are invoked before built-in resolvers
   * except for those that rely on the presence of annotations (e.g.
   * {@code @RequestParameter}, {@code @PathVariable}, etc.).
   * The latter can  be customized by configuring the
   * {@link RequestMappingHandlerAdapter} directly.
   * @param argumentResolvers the list of custom converters;
   *   initially an empty list.
   */
  protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
  }

  /**
   * Add custom {@link HandlerMethodReturnValueHandler}s in addition to the
   * ones registered by default.
   * <p>Custom return value handlers are invoked before built-in ones except
   * for those that rely on the presence of annotations (e.g.
   * {@code @ResponseBody}, {@code @ModelAttribute}, etc.).
   * The latter can be customized by configuring the
   * {@link RequestMappingHandlerAdapter} directly.
   * @param returnValueHandlers the list of custom handlers;
   * initially an empty list.
   */
  protected void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
  }

  /**
   * Provides access to the shared {@link HttpMessageConverter}s used by the
   * {@link RequestMappingHandlerAdapter} and the
   * {@link ExceptionHandlerExceptionResolver}.
   * This method cannot be overridden.
   * Use {@link #configureMessageConverters(List)} instead.
   * Also see {@link #addDefaultHttpMessageConverters(List)} that can be
   * used to add default message converters.
   */
  protected final List<HttpMessageConverter<?>> getMessageConverters() {
    if (this.messageConverters == null) {
      this.messageConverters = new ArrayList<HttpMessageConverter<?>>();
      configureMessageConverters(this.messageConverters);
      if (this.messageConverters.isEmpty()) {
        addDefaultHttpMessageConverters(this.messageConverters);
      }
    }
    return this.messageConverters;
  }

  /**
   * Override this method to add custom {@link HttpMessageConverter}s to use
   * with the {@link RequestMappingHandlerAdapter} and the
   * {@link ExceptionHandlerExceptionResolver}. Adding converters to the
   * list turns off the default converters that would otherwise be registered
   * by default. Also see {@link #addDefaultHttpMessageConverters(List)} that
   * can be used to add default message converters.
   * @param converters a list to add message converters to;
   * initially an empty list.
   */
  protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  }

  /**
   * Adds a set of default HttpMessageConverter instances to the given list.
   * Subclasses can call this method from {@link #configureMessageConverters(List)}.
   * @param messageConverters the list to add the default message converters to
   */
  protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
    StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
    stringConverter.setWriteAcceptCharset(false);

    messageConverters.add(new ByteArrayHttpMessageConverter());
    messageConverters.add(stringConverter);
    messageConverters.add(new ResourceHttpMessageConverter());
    messageConverters.add(new SourceHttpMessageConverter<Source>());
    messageConverters.add(new AllEncompassingFormHttpMessageConverter());

    if (romePresent) {
      messageConverters.add(new AtomFeedHttpMessageConverter());
      messageConverters.add(new RssChannelHttpMessageConverter());
    }

    if (jackson2XmlPresent) {
      messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
    }
    else if (jaxb2Present) {
      messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
    }

    if (jackson2Present) {
      messageConverters.add(new MappingJackson2HttpMessageConverter());
    }
    else if (gsonPresent) {
      messageConverters.add(new GsonHttpMessageConverter());
    }
  }

  /**
   * Override this method to add custom {@link Converter}s and {@link Formatter}s.
   */
  protected void addFormatters(FormatterRegistry registry) {
  }

  /**
   * Override this method to configure asynchronous request processing options.
   * @see AsyncSupportConfigurer
   */
  public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
  }

  /**
   * Return an instance of {@link CompositeUriComponentsContributor} for use with
   * {@link org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder}.
   */
  @Bean
  public CompositeUriComponentsContributor mvcUriComponentsContributor() {
    return new CompositeUriComponentsContributor(
        requestMappingHandlerAdapter().getArgumentResolvers(), mvcConversionService());
  }

  /**
   * Returns a {@link HttpRequestHandlerAdapter} for processing requests
   * with {@link HttpRequestHandler}s.
   */
  @Bean
  public HttpRequestHandlerAdapter httpRequestHandlerAdapter() {
    return new HttpRequestHandlerAdapter();
  }

  /**
   * Returns a {@link SimpleControllerHandlerAdapter} for processing requests
   * with interface-based controllers.
   */
  @Bean
  public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() {
    return new SimpleControllerHandlerAdapter();
  }

  /**
   * Returns a {@link HandlerExceptionResolverComposite} containing a list
   * of exception resolvers obtained either through
   * {@link #configureHandlerExceptionResolvers(List)} or through
   * {@link #addDefaultHandlerExceptionResolvers(List)}.
   * <p><strong>Note:</strong> This method cannot be made final due to CGLib
   * constraints. Rather than overriding it, consider overriding
   * {@link #configureHandlerExceptionResolvers(List)}, which allows
   * providing a list of resolvers.
   */
  @Bean
  public HandlerExceptionResolver handlerExceptionResolver() {
    List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<HandlerExceptionResolver>();
    configureHandlerExceptionResolvers(exceptionResolvers);

    if (exceptionResolvers.isEmpty()) {
      addDefaultHandlerExceptionResolvers(exceptionResolvers);
    }

    HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
    composite.setOrder(0);
    composite.setExceptionResolvers(exceptionResolvers);
    return composite;
  }

  /**
   * Override this method to configure the list of
   * {@link HandlerExceptionResolver}s to use. Adding resolvers to the list
   * turns off the default resolvers that would otherwise be registered by
   * default. Also see {@link #addDefaultHandlerExceptionResolvers(List)}
   * that can be used to add the default exception resolvers.
   * @param exceptionResolvers a list to add exception resolvers to;
   * initially an empty list.
   */
  protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
  }

  /**
   * A method available to subclasses for adding default {@link HandlerExceptionResolver}s.
   * <p>Adds the following exception resolvers:
   * <ul>
   * <li>{@link ExceptionHandlerExceptionResolver}
   * for handling exceptions through @{@link ExceptionHandler} methods.
   * <li>{@link ResponseStatusExceptionResolver}
   * for exceptions annotated with @{@link ResponseStatus}.
   * <li>{@link DefaultHandlerExceptionResolver}
   * for resolving known Spring exception types
   * </ul>
   */
  protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
    ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new ExceptionHandlerExceptionResolver();
    exceptionHandlerExceptionResolver.setContentNegotiationManager(mvcContentNegotiationManager());
    exceptionHandlerExceptionResolver.setMessageConverters(getMessageConverters());
    if (jackson2Present) {
      List<ResponseBodyAdvice<?>> interceptors = new ArrayList<ResponseBodyAdvice<?>>();
      interceptors.add(new JsonViewResponseBodyAdvice());
      exceptionHandlerExceptionResolver.setResponseBodyAdvice(interceptors);
    }
    exceptionHandlerExceptionResolver.setApplicationContext(this.applicationContext);
    exceptionHandlerExceptionResolver.afterPropertiesSet();
    exceptionResolvers.add(exceptionHandlerExceptionResolver);

    ResponseStatusExceptionResolver responseStatusExceptionResolver = new ResponseStatusExceptionResolver();
    responseStatusExceptionResolver.setMessageSource(this.applicationContext);
    exceptionResolvers.add(responseStatusExceptionResolver);

    exceptionResolvers.add(new DefaultHandlerExceptionResolver());
  }

  /**
   * Register a {@link ViewResolverComposite} that contains a chain of view resolvers
   * to use for view resolution.
   * By default this resolver is ordered at 0 unless content negotiation view
   * resolution is used in which case the order is raised to
   * {@link org.springframework.core.Ordered#HIGHEST_PRECEDENCE
   * Ordered.HIGHEST_PRECEDENCE}.
   * <p>If no other resolvers are configured,
   * {@link ViewResolverComposite#resolveViewName(String, Locale)} returns null in order
   * to allow other potential {@link ViewResolver} beans to resolve views.
   * @since 4.1
   */
  @Bean
  public ViewResolver mvcViewResolver() {
    ViewResolverRegistry registry = new ViewResolverRegistry();
    registry.setContentNegotiationManager(mvcContentNegotiationManager());
    registry.setApplicationContext(this.applicationContext);
    configureViewResolvers(registry);

    if (registry.getViewResolvers().isEmpty()) {
      String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
          this.applicationContext, ViewResolver.class, true, false);
      if (names.length == 1) {
        registry.getViewResolvers().add(new InternalResourceViewResolver());
      }
    }

    ViewResolverComposite composite = new ViewResolverComposite();
    composite.setOrder(registry.getOrder());
    composite.setViewResolvers(registry.getViewResolvers());
    composite.setApplicationContext(this.applicationContext);
    composite.setServletContext(this.servletContext);
    return composite;
  }

  /**
   * Override this method to configure view resolution.
   * @see ViewResolverRegistry
   */
  protected void configureViewResolvers(ViewResolverRegistry registry) {
  }


  private static final class EmptyHandlerMapping extends AbstractHandlerMapping {

    @Override
    protected Object getHandlerInternal(HttpServletRequest request) {
      return null;
    }
  }


  private static final class NoOpValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
      return false;
    }

    @Override
    public void validate(Object target, Errors errors) {
    }
  }

}
TOP

Related Classes of org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport$NoOpValidator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
ga('send', 'pageview');