Spring 源码学习(十一)—— webmvc 配置

发布于:2025-08-18 ⋅ 阅读:(15) ⋅ 点赞:(0)

 

1. WebMvcConfigurationSupport 类

        WebMvcConfigurationSupport 类提供了对 MVC 的配置支持;

1.1 变量

1.1.1 静态变量

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {

	private static final boolean romePresent;

	private static final boolean jaxb2Present;

	private static final boolean jackson2Present;

	private static final boolean jackson2XmlPresent;

	private static final boolean jackson2SmilePresent;

	private static final boolean jackson2CborPresent;

	private static final boolean gsonPresent;

	private static final boolean jsonbPresent;

	static {
		ClassLoader classLoader = WebMvcConfigurationSupport.class.getClassLoader();
		romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);
		jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
		jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
				ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
		jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
		jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
		jackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
		gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
		jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);
	}
}

        WebMvcConfigurationSupport 类中静态变量有 8 个,用于检测当前可用的序列化/反序列化库:其中 romePresent 属性通过检测 com.rometools.rome.feed.WireFeed 类是否存在来检测 ROME 库(RSS/Atom 订阅处理)是否存在,jaxb2Present 通过 javax.xml.bind.Binder 类检测 JAXB 库(XML绑定标准(JavaEE 标准)),jackson2Present 同时检查 com.fasterxml.jackson.databind.ObjectMapper 与 com.fasterxml.jackson.core.JsonGenerator 类来判断是否引入了 Jackson JSON 库(JSON 核心处理库),jackson2XmlPresent 通过 com.fasterxml.jackson.dataformat.xml.XmlMapper 类检测 Jackson XML 库(XML处理扩展),jackson2SmilePresent 通过 com.fasterxml.jackson.dataformat.smile.SmileFactory 类检测 Jackson Smile 库(二进制JSON格式处理),jackson2CborPresent 通过 com.fasterxml.jackson.dataformat.cbor.CBORFactory 类检测 Jackson CBOR 库(类似 MessagePack 的简洁二进制对象表示),gsonPresent 通过 com.google.gson.Gson 类检测 Google Gson 库(Google 的 JSON 库),jsonbPresent 通过 javax.json.bind.Jsonb 类检测 JSON-B 库(JavaEE标准JSON处理)。

1.1.2 类变量

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {

	@Nullable
	private ApplicationContext applicationContext;

	@Nullable
	private ServletContext servletContext;

	@Nullable
	private List<Object> interceptors;

	@Nullable
	private PathMatchConfigurer pathMatchConfigurer;

	@Nullable
	private ContentNegotiationManager contentNegotiationManager;

	@Nullable
	private List<HandlerMethodArgumentResolver> argumentResolvers;

	@Nullable
	private List<HandlerMethodReturnValueHandler> returnValueHandlers;

	@Nullable
	private List<HttpMessageConverter<?>> messageConverters;

	@Nullable
	private Map<String, CorsConfiguration> corsConfigurations;
}

        WebMvcConfigurationSupport 类中的 applicationContext 与 servletContext 属性分别保存的是当前应用程序与 Servlet 上下文,interceptors 为当前程序注册的拦截器缓存列表,pathMatchConfigurer 属性为路径匹配配置,contentNegotiationManager 属性用于控制客户端请求类型

1.2 方法

        WebMvcConfigurationSupport 类作为一个 spring 配置类,理所当然通过 Bean 注解声明了并向上下文中注入了很多必要对象,因此本文将基于使用 Bean 修饰的方法入手,即从配置对象入手对该配置类进行方法分析。

1.2.1 requestMappingHandlerMapping 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	@SuppressWarnings("deprecation")
	public RequestMappingHandlerMapping requestMappingHandlerMapping(
			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {

		RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
		mapping.setOrder(0);
		mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
		mapping.setContentNegotiationManager(contentNegotiationManager);
		mapping.setCorsConfigurations(getCorsConfigurations());

		PathMatchConfigurer configurer = getPathMatchConfigurer();

		Boolean useSuffixPatternMatch = configurer.isUseSuffixPatternMatch();
		if (useSuffixPatternMatch != null) {
			mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
		}
		Boolean useRegisteredSuffixPatternMatch = configurer.isUseRegisteredSuffixPatternMatch();
		if (useRegisteredSuffixPatternMatch != null) {
			mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);
		}
		Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
		if (useTrailingSlashMatch != null) {
			mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
		}

		UrlPathHelper pathHelper = configurer.getUrlPathHelper();
		if (pathHelper != null) {
			mapping.setUrlPathHelper(pathHelper);
		}
		PathMatcher pathMatcher = configurer.getPathMatcher();
		if (pathMatcher != null) {
			mapping.setPathMatcher(pathMatcher);
		}
		Map<String, Predicate<Class<?>>> pathPrefixes = configurer.getPathPrefixes();
		if (pathPrefixes != null) {
			mapping.setPathPrefixes(pathPrefixes);
		}

		return mapping;
	}
}

        requestMappingHandlerMapping 方法用于声明和构建 RequestMappingHandlerMapping 对象及 DispatcherServlet 类中需要的 HandlerMapping 对象一个实现,执行顺序为 0,表示首先进行执行:其首先通过 createRequestMappingHandlerMapping 方法创建基础 RequestMappingHandlerMapping 对象,并将其排序值置为 1,使用 getInterceptors 为其设置拦截器数组,将其 contentNegotiationManager 属性初始化为注入的 contentNegotiationManager 值,然后通过 getCorsConfigurations 方法获取跨域配置并保存到 CorsConfigurations 属性之中;之后根据 getPathMatchConfigurer 方法获取到的路径匹配配置项设置不同的属性值,其设置的属性值有是否进行后缀匹配 useSuffixPatternMatch(默认 false)、后缀匹配模式是否只用于扩展路径的 useRegisteredSuffixPatternMatch (默认 false)、是否默认是否可默认匹配后缀反斜杠 useTrailingSlashMatch(默认 true,示例:/users 与 /users/ 都可匹配)、URL 匹配辅助器 urlPathHelper、路径匹配器 pathMatcher 及前缀断言映射 pathPrefixes;在设置完上述属性后返回复制完成的 RequestMappingHandlerMapping 对象。

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
		return new RequestMappingHandlerMapping();
	}
}

        WebMvcConfigurationSupport 声明的 createRequestMappingHandlerMapping 方法直接创建空 RequestMappingHandlerMapping 对象并返回;

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	protected final Object[] getInterceptors(
			FormattingConversionService mvcConversionService,
			ResourceUrlProvider mvcResourceUrlProvider) {
		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();
	}

	protected void addInterceptors(InterceptorRegistry registry) {
	}
}

        WebMvcConfigurationSupport 声明的 getInterceptors 方法首先会通过 interceptors 属性值判断是否已经加载过拦截器,尚未加载则会使用 mvcConversionService 与 mvcResourceUrlProvider 参数创建 ConversionServiceExposingInterceptor 对象与 ResourceUrlProviderExposingInterceptor 对象,并使用新建的 InterceptorRegistry 注册器对象将上述两对象及子类通过 addInterceptors 方法注册的拦截器转换一下然后赋值到 interceptors 属性之中并在最后返回 interceptors 属性值;

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	protected final Map<String, CorsConfiguration> getCorsConfigurations() {
		if (this.corsConfigurations == null) {
			CorsRegistry registry = new CorsRegistry();
			addCorsMappings(registry);
			this.corsConfigurations = registry.getCorsConfigurations();
		}
		return this.corsConfigurations;
	}

	protected void addCorsMappings(CorsRegistry registry) {
	}
}

        getCorsConfigurations 方法用于获取跨域配置,其和 getInterceptors 方法一样也是可以通过子类实现 addCorsMappings 方法进行扩展,但在  WebMvcConfigurationSupport 类中不提供默认值;

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	protected PathMatchConfigurer getPathMatchConfigurer() {
		if (this.pathMatchConfigurer == null) {
			this.pathMatchConfigurer = new PathMatchConfigurer();
			configurePathMatch(this.pathMatchConfigurer);
		}
		return this.pathMatchConfigurer;
	}

	protected void configurePathMatch(PathMatchConfigurer configurer) {
	}
}

        getPathMatchConfigurer 方法与 getInterceptors 方法一样也是可以通过子类实现 configurePathMatch 方法进行扩展,其在  WebMvcConfigurationSupport 类中也不提供默认值;

1.2.2 mvcPathMatcher 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public PathMatcher mvcPathMatcher() {
		PathMatcher pathMatcher = getPathMatchConfigurer().getPathMatcher();
		return (pathMatcher != null ? pathMatcher : new AntPathMatcher());
	}
}

        mvcPathMatcher 方法首先尝试从 pathMatchConfigurer 属性中获取 pathMatcher 对象来注入,否则直接新建 AntPathMatcher 对象进行注入; 

1.2.3 mvcUrlPathHelper 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public UrlPathHelper mvcUrlPathHelper() {
		UrlPathHelper pathHelper = getPathMatchConfigurer().getUrlPathHelper();
		return (pathHelper != null ? pathHelper : new UrlPathHelper());
	}
}

        mvcUrlPathHelper 方法首先也会尝试从 pathMatchConfigurer 属性中获取 mvcUrlPathHelper 对象注入,否则注入新建的 UrlPathHelper 对象; 

1.2.4 mvcContentNegotiationManager 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public ContentNegotiationManager mvcContentNegotiationManager() {
		if (this.contentNegotiationManager == null) {
			ContentNegotiationConfigurer configurer = new ContentNegotiationConfigurer(this.servletContext);
			configurer.mediaTypes(getDefaultMediaTypes());
			configureContentNegotiation(configurer);
			this.contentNegotiationManager = configurer.buildContentNegotiationManager();
		}
		return this.contentNegotiationManager;
	}

	protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
	}
}

        mvcContentNegotiationManager 方法在 contentNegotiationManager 属性不为空时直接返回,否则首先会使用 servlet 上下文创建 ContentNegotiationConfigurer 配置,同时将配置的媒体类型设置 getDefaultMediaTypes 方法值并使用 configureContentNegotiation 将配置交由子类扩展,最后调用 ContentNegotiationConfigurer 配置对象的 buildContentNegotiationManager 方法建造 ContentNegotiationManager 对象并保存到 contentNegotiationManager 属性之后然后返回;

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	protected Map<String, MediaType> getDefaultMediaTypes() {
		Map<String, MediaType> map = new HashMap<>(4);
		if (romePresent) {
			map.put("atom", MediaType.APPLICATION_ATOM_XML);
			map.put("rss", MediaType.APPLICATION_RSS_XML);
		}
		if (jaxb2Present || jackson2XmlPresent) {
			map.put("xml", MediaType.APPLICATION_XML);
		}
		if (jackson2Present || gsonPresent || jsonbPresent) {
			map.put("json", MediaType.APPLICATION_JSON);
		}
		if (jackson2SmilePresent) {
			map.put("smile", MediaType.valueOf("application/x-jackson-smile"));
		}
		if (jackson2CborPresent) {
			map.put("cbor", MediaType.APPLICATION_CBOR);
		}
		return map;
	}
}

        getDefaultMediaTypes 方法根据常量值(即是否引入对应的序列化/反序列化包)来配置对应的媒体支持;romePresent 常量为 true 即引入了 ROME 库后支持 APPLICATION_ATOM_XML 与 APPLICATION_RSS_XML,jaxb2Present 或 jackson2XmlPresent 常量为 true 即引入了 JAXB 或 Jackson XML 库后支持 APPLICATION_XML,jackson2Present、gsonPresent 或 jsonbPresent 常量为 true 即引入了 Jackson JSON、Google Gson 或 JSON-B 库后支持 APPLICATION_JSON ,jackson2SmilePresent 常量为 true 即引入了 Jackson Smile 库后支持 application/x-jackson-smile,jackson2CborPresent 常量为 true 即引入了 Jackson CBOR 库后支持 APPLICATION_CBOR。

1.2.5 viewControllerHandlerMapping 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	@Nullable
	public HandlerMapping viewControllerHandlerMapping(
			@Qualifier("mvcPathMatcher") PathMatcher pathMatcher,
			@Qualifier("mvcUrlPathHelper") UrlPathHelper urlPathHelper,
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
		ViewControllerRegistry registry = new ViewControllerRegistry(this.applicationContext);
		addViewControllers(registry);

		AbstractHandlerMapping handlerMapping = registry.buildHandlerMapping();
		if (handlerMapping == null) {
			return null;
		}
		handlerMapping.setPathMatcher(pathMatcher);
		handlerMapping.setUrlPathHelper(urlPathHelper);
		handlerMapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
		handlerMapping.setCorsConfigurations(getCorsConfigurations());
		return handlerMapping;
	}

	protected void addViewControllers(ViewControllerRegistry registry) {
	}
}

        viewControllerHandlerMapping 方法首先使用 applicationContext 上下文创建 ViewControllerRegistry 注册器,随后使用 addViewControllers 方法对其进行扩展同时调用其 buildHandlerMapping 方法建造 AbstractHandlerMapping 对象,若未成功创建直接返回 null;随后依次为建造的 AbstractHandlerMapping 对象依次设置 pathMatcher、urlPathHelper、Interceptor 拦截器列表及 corsConfigurations 跨域配置。

1.2.6 BeanNameUrlHandlerMapping 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public BeanNameUrlHandlerMapping beanNameHandlerMapping(
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {

		BeanNameUrlHandlerMapping mapping = new BeanNameUrlHandlerMapping();
		mapping.setOrder(2);
		mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
		mapping.setCorsConfigurations(getCorsConfigurations());
		return mapping;
	}
}

        beanNameHandlerMapping 方法创建的 BeanNameUrlHandlerMapping 对象执行顺序为 2,其直接新建 BeanNameUrlHandlerMapping 对象并为其设置 nterceptor 拦截器列表及 corsConfigurations 跨配置并返回。

1.2.7 routerFunctionMapping 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public RouterFunctionMapping routerFunctionMapping(
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {

		RouterFunctionMapping mapping = new RouterFunctionMapping();
		mapping.setOrder(3);
		mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
		mapping.setCorsConfigurations(getCorsConfigurations());
		mapping.setMessageConverters(getMessageConverters());
		return mapping;
	}
}

        routerFunctionMapping 方法创建的 RouterFunctionMapping 对象执行顺序为 3,直接新建 RouterFunctionMapping 对象并为其设置 nterceptor 拦截器列表、corsConfigurations 跨配置及 HttpMessageConverter 消息转换器列表并返回。

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	protected final List<HttpMessageConverter<?>> getMessageConverters() {
		if (this.messageConverters == null) {
			this.messageConverters = new ArrayList<>();
			configureMessageConverters(this.messageConverters);
			if (this.messageConverters.isEmpty()) {
				addDefaultHttpMessageConverters(this.messageConverters);
			}
			extendMessageConverters(this.messageConverters);
		}
		return this.messageConverters;
	}

	protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
	}

	protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
	}
}

        getMessageConverters 方法在当前 messageConverters 属性不为空时直接返回,否则首先通过 configureMessageConverters 方法在子类中配置消息转换器,若未从子类获取到,则会调用 addDefaultHttpMessageConverters 方法设置默认消息转化器,最后在配置完后通过 extendMessageConverters 方法提供子类对消息转化器的扩展功能。

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
		messageConverters.add(new ByteArrayHttpMessageConverter());
		messageConverters.add(new StringHttpMessageConverter());
		messageConverters.add(new ResourceHttpMessageConverter());
		messageConverters.add(new ResourceRegionHttpMessageConverter());
		try {
			messageConverters.add(new SourceHttpMessageConverter<>());
		}
		catch (Throwable ex) {
			// Ignore when no TransformerFactory implementation is available...
		}
		messageConverters.add(new AllEncompassingFormHttpMessageConverter());

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

		if (jackson2XmlPresent) {
			Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
			if (this.applicationContext != null) {
				builder.applicationContext(this.applicationContext);
			}
			messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
		}
		else if (jaxb2Present) {
			messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
		}

		if (jackson2Present) {
			Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
			if (this.applicationContext != null) {
				builder.applicationContext(this.applicationContext);
			}
			messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
		}
		else if (gsonPresent) {
			messageConverters.add(new GsonHttpMessageConverter());
		}
		else if (jsonbPresent) {
			messageConverters.add(new JsonbHttpMessageConverter());
		}

		if (jackson2SmilePresent) {
			Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.smile();
			if (this.applicationContext != null) {
				builder.applicationContext(this.applicationContext);
			}
			messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
		}
		if (jackson2CborPresent) {
			Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.cbor();
			if (this.applicationContext != null) {
				builder.applicationContext(this.applicationContext);
			}
			messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
		}
	}
}

        addDefaultHttpMessageConverters 方法首先将 ByteArrayHttpMessageConverter、StringHttpMessageConverter、ResourceHttpMessageConverter、ResourceRegionHttpMessageConverter、SourceHttpMessageConverter 及 AllEncompassingFormHttpMessageConverter 保存到 messageConverters 参数之中,随后也会根据常量值即通过判断支持不同的序列化方式,来注入对应的消息转换器。

1.2.8 resourceHandlerMapping 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	@Nullable
	public HandlerMapping resourceHandlerMapping(
			@Qualifier("mvcUrlPathHelper") UrlPathHelper urlPathHelper,
			@Qualifier("mvcPathMatcher") PathMatcher pathMatcher,
			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {

		Assert.state(this.applicationContext != null, "No ApplicationContext set");
		Assert.state(this.servletContext != null, "No ServletContext set");

		ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext,
				this.servletContext, contentNegotiationManager, urlPathHelper);
		addResourceHandlers(registry);

		AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
		if (handlerMapping == null) {
			return null;
		}
		handlerMapping.setPathMatcher(pathMatcher);
		handlerMapping.setUrlPathHelper(urlPathHelper);
		handlerMapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
		handlerMapping.setCorsConfigurations(getCorsConfigurations());
		return handlerMapping;
	}

	protected void addResourceHandlers(ResourceHandlerRegistry registry) {
	}
}

        resourceHandlerMapping 方法首先创建 ResourceHandlerRegistry 对象同时调用 addResourceHandlers 方法在子类上对其进行补充,随后尝试从其中获取 AbstractHandlerMapping 对象;若不为空则依次设置 pathMatcher、urlPathHelper、Interceptor 拦截器列表及 corsConfigurations 跨域配置。

1.2.9 defaultServletHandlerMapping 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	@Nullable
	public HandlerMapping defaultServletHandlerMapping() {
		Assert.state(this.servletContext != null, "No ServletContext set");
		DefaultServletHandlerConfigurer configurer = new DefaultServletHandlerConfigurer(this.servletContext);
		configureDefaultServletHandling(configurer);
		return configurer.buildHandlerMapping();
	}

	protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
	}
}

        defaultServletHandlerMapping 方法通过 DefaultServletHandlerConfigurer 对象与 configureDefaultServletHandling 方法配置默认 Servlet  处理器并返回。

 1.2.10 requestMappingHandlerAdapter 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcValidator") Validator validator) {

		RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
		adapter.setContentNegotiationManager(contentNegotiationManager);
		adapter.setMessageConverters(getMessageConverters());
		adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
		adapter.setCustomArgumentResolvers(getArgumentResolvers());
		adapter.setCustomReturnValueHandlers(getReturnValueHandlers());

		if (jackson2Present) {
			adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
			adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
		}

		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;
	}

	protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
		return new RequestMappingHandlerAdapter();
	}

	protected final List<HandlerMethodArgumentResolver> getArgumentResolvers() {
		if (this.argumentResolvers == null) {
			this.argumentResolvers = new ArrayList<>();
			addArgumentResolvers(this.argumentResolvers);
		}
		return this.argumentResolvers;
	}

	protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
	}

	protected final List<HandlerMethodReturnValueHandler> getReturnValueHandlers() {
		if (this.returnValueHandlers == null) {
			this.returnValueHandlers = new ArrayList<>();
			addReturnValueHandlers(this.returnValueHandlers);
		}
		return this.returnValueHandlers;
	}

	protected void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
	}
}

        requestMappingHandlerAdapter 方法首先通过 createRequestMappingHandlerAdapter 方法创建 RequestMappingHandlerAdapter 对象,并依次设置 contentNegotiationManager、messageConverters、webBindingInitializer、customArgumentResolvers 以及 customReturnValueHandlers 属性值,同时在引入了 Jackson JSON 核心库是分别将 requestBodyAdvice 与 responseBodyAdvice 属性设置为 JsonViewRequestBodyAdvice 与 JsonViewResponseBodyAdvice 对象,接下来根据 configureAsyncSupport 方法配置结果进行异步配置然后返回;

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer(
			FormattingConversionService mvcConversionService, Validator mvcValidator) {

		ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
		initializer.setConversionService(mvcConversionService);
		initializer.setValidator(mvcValidator);
		MessageCodesResolver messageCodesResolver = getMessageCodesResolver();
		if (messageCodesResolver != null) {
			initializer.setMessageCodesResolver(messageCodesResolver);
		}
		return initializer;
	}

	@Nullable
	protected MessageCodesResolver getMessageCodesResolver() {
		return null;
	}
}

        getConfigurableWebBindingInitializer 方法创建了 ConfigurableWebBindingInitializer 对象并依次设置 FormattingConversionService、Validator 与 MessageCodesResolver 属性并返回;

1.2.11 handlerFunctionAdapter 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public HandlerFunctionAdapter handlerFunctionAdapter() {
		return new HandlerFunctionAdapter();
	}
}

        handlerFunctionAdapter 方法直接注入新建的 HandlerFunctionAdapter 的对象。

 1.2.12 mvcConversionService 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public FormattingConversionService mvcConversionService() {
		FormattingConversionService conversionService = new DefaultFormattingConversionService();
		addFormatters(conversionService);
		return conversionService;
	}

	protected void addFormatters(FormatterRegistry registry) {
	}
}

        mvcConversionService 方法新建 DefaultFormattingConversionService 对象并 addFormatters 方法用于子类扩展并返回。

1.2.13 mvcValidator 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@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 | LinkageError ex) {
					throw new BeanInitializationException("Failed to resolve default validator class", ex);
				}
				validator = (Validator) BeanUtils.instantiateClass(clazz);
			}
			else {
				validator = new NoOpValidator();
			}
		}
		return validator;
	}

	@Nullable
	protected Validator getValidator() {
		return null;
	}
}

        mvcValidator 方法首先尝试从 getValidator 中获取自定义 Validator 验证器,未获取到时则会判断是否引入了 javax.validation.Validator 对象,若引入了直接创建 org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean 类并返回,否则创建 NoOpValidator 对象并返回。

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	private static final class NoOpValidator implements Validator {

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

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

}

        NoOpValidator 为 Validator 接口的空实现,supports 方法直接返回 false,同时 validate 方法只有一个空实现

1.2.14 mvcUriComponentsContributor 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public CompositeUriComponentsContributor mvcUriComponentsContributor(
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("requestMappingHandlerAdapter") RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
		return new CompositeUriComponentsContributor(
				requestMappingHandlerAdapter.getArgumentResolvers(), conversionService);
	}
}

        mvcUriComponentsContributor 方法直接创建 CompositeUriComponentsContributor 对象然后返回。

1.2.15 httpRequestHandlerAdapter 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public HttpRequestHandlerAdapter httpRequestHandlerAdapter() {
		return new HttpRequestHandlerAdapter();
	}
}

        HttpRequestHandlerAdapter 方法直接创建 HttpRequestHandlerAdapter 对象然后返回。

1.2.16 simpleControllerHandlerAdapter 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() {
		return new SimpleControllerHandlerAdapter();
	}
}

        simpleControllerHandlerAdapter 方法直接创建 SimpleControllerHandlerAdapter 对象然后返回。

1.2.17 handlerExceptionResolver 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public HandlerExceptionResolver handlerExceptionResolver(
			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
		List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();
		configureHandlerExceptionResolvers(exceptionResolvers);
		if (exceptionResolvers.isEmpty()) {
			addDefaultHandlerExceptionResolvers(exceptionResolvers, contentNegotiationManager);
		}
		extendHandlerExceptionResolvers(exceptionResolvers);
		HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
		composite.setOrder(0);
		composite.setExceptionResolvers(exceptionResolvers);
		return composite;
	}

	protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
	}

	protected void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
	}
}

        handlerExceptionResolver 方法直接首先尝试从 configureHandlerExceptionResolvers 方法从子类中获取自定义异常解析器,若未配置则使用 addDefaultHandlerExceptionResolvers 方法设置默认异常解析器列表,随后使用 HandlerExceptionResolverComposite 对其进行封装并将其执行顺序设置为 0 ,然后返回。

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers,
			ContentNegotiationManager mvcContentNegotiationManager) {

		ExceptionHandlerExceptionResolver exceptionHandlerResolver = createExceptionHandlerExceptionResolver();
		exceptionHandlerResolver.setContentNegotiationManager(mvcContentNegotiationManager);
		exceptionHandlerResolver.setMessageConverters(getMessageConverters());
		exceptionHandlerResolver.setCustomArgumentResolvers(getArgumentResolvers());
		exceptionHandlerResolver.setCustomReturnValueHandlers(getReturnValueHandlers());
		if (jackson2Present) {
			exceptionHandlerResolver.setResponseBodyAdvice(
					Collections.singletonList(new JsonViewResponseBodyAdvice()));
		}
		if (this.applicationContext != null) {
			exceptionHandlerResolver.setApplicationContext(this.applicationContext);
		}
		exceptionHandlerResolver.afterPropertiesSet();
		exceptionResolvers.add(exceptionHandlerResolver);

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

		exceptionResolvers.add(new DefaultHandlerExceptionResolver());
	}

	protected ExceptionHandlerExceptionResolver createExceptionHandlerExceptionResolver() {
		return new ExceptionHandlerExceptionResolver();
	}
}

        addDefaultHandlerExceptionResolvers 调用 createExceptionHandlerExceptionResolver 创建 ExceptionHandlerExceptionResolver 对象作为基处理器,然后设置 mvcContentNegotiationManager、MessageConverter 列表、ArgumentResolver 处理器列表及 ReturnValueHandler 列表;随后若引入了 jackson JSON,会将其 ResponseBodyAdvice 设置为 JsonViewResponseBodyAdvice 对象;最后调用其 afterPropertiesSet 方法进行后处理并在处理完成后将其保存到 exceptionResolvers 变量之中,随后依次向该变量中添加 ResponseStatusExceptionResolver 与 DefaultHandlerExceptionResolver 对象然后返回;

1.2.18 handlerExceptionResolver 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	@Bean
	public ViewResolver mvcViewResolver(
			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
		ViewResolverRegistry registry =
				new ViewResolverRegistry(contentNegotiationManager, this.applicationContext);
		configureViewResolvers(registry);

		if (registry.getViewResolvers().isEmpty() && this.applicationContext != null) {
			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());
		if (this.applicationContext != null) {
			composite.setApplicationContext(this.applicationContext);
		}
		if (this.servletContext != null) {
			composite.setServletContext(this.servletContext);
		}
		return composite;
	}

	protected void configureViewResolvers(ViewResolverRegistry registry) {
	}
}

        mvcViewResolver 方法首先使用 contentNegotiationManager 与 applicationContext 值创建 ViewResolverRegistry 对象并调用 configureViewResolvers 方法对其进行配置;之后若未配置任何 viewResolver 解析器、当前上下文不为空且上下文中只拥有一个 ViewResolver 对象时则会向该注册器中添加一个 InternalResourceViewResolver 对象;最后创建 ViewResolverComposite 对象并依次设置执行顺序、ViewResolver 解析器列表、程序上下文及 servlet 上下文然后返回。

2. DelegatingWebMvcConfiguration 类

        DelegatingWebMvcConfiguration 类提供了对 spring-mvc 配置的自定义扩展;

2.1 变量

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

	private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

	@Autowired(required = false)
	public void setConfigurers(List<WebMvcConfigurer> configurers) {
		if (!CollectionUtils.isEmpty(configurers)) {
			this.configurers.addWebMvcConfigurers(configurers);
		}
	}
}

        DelegatingWebMvcConfiguration 类只有一个用于保存所有自定义 WebMvcConfigurer 配置对象的 WebMvcConfigurerComposite 类型 configurers 属性,setConfigurers 方法直接将上下文中的所有 WebMvcConfigurer 对象保存到 configurers 属性之中;

2.2 方法

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

	@Override
	protected void configurePathMatch(PathMatchConfigurer configurer) {
		this.configurers.configurePathMatch(configurer);
	}
    ...
}

        DelegatingWebMvcConfiguration 所有方法都是用于对 Web-mvc 自定义配置,其都是通过调用 configurers 属性的对应方法实现的;

2.3 WebMvcConfigurer 接口

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

	default void configurePathMatch(PathMatchConfigurer configurer) {
	}

    ...

	@Nullable
	default Validator getValidator() {
		return null;
	}
    ...
}

        WebMvcConfigurer 的所有接口都拥有默认实现,其中没有返回值的方法直接默认空实现,拥有返回值的方法默认返回 null;

2.4 WebMvcConfigurerComposite 类

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

	private final List<WebMvcConfigurer> delegates = new ArrayList<>();


	public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {
		if (!CollectionUtils.isEmpty(configurers)) {
			this.delegates.addAll(configurers);
		}
	}
}

        WebMvcConfigurerComposite 类只有一个用于保存第一次通过 addWebMvcConfigurers 方法注入的 WebMvcConfigurer 对象列表的 delegates 属性;

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

	@Override
	public void configurePathMatch(PathMatchConfigurer configurer) {
		for (WebMvcConfigurer delegate : this.delegates) {
			delegate.configurePathMatch(configurer);
		}
	}

    ...

	@Override
	public Validator getValidator() {
		Validator selected = null;
		for (WebMvcConfigurer configurer : this.delegates) {
			Validator validator = configurer.getValidator();
			if (validator != null) {
				if (selected != null) {
					throw new IllegalStateException("No unique Validator found: {" +
							selected + ", " + validator + "}");
				}
				selected = validator;
			}
		}
		return selected;
	}
    ...
}

        WebMvcConfigurerComposite 的方法实现也是分成两种,一种是没返回值的,依次执行 delegates 属性中的对应方法,拥有返回值的则会验证 delegates 中只有一个元素或更少实现了该方法,存在多个实现了由返回值方法的对象时直接抛出异常;


网站公告

今日签到

点亮在社区的每一天
去签到