当前位置: 首页 > news >正文

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

 

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 {@Nullableprivate ApplicationContext applicationContext;@Nullableprivate ServletContext servletContext;@Nullableprivate List<Object> interceptors;@Nullableprivate PathMatchConfigurer pathMatchConfigurer;@Nullableprivate ContentNegotiationManager contentNegotiationManager;@Nullableprivate List<HandlerMethodArgumentResolver> argumentResolvers;@Nullableprivate List<HandlerMethodReturnValueHandler> returnValueHandlers;@Nullableprivate List<HttpMessageConverter<?>> messageConverters;@Nullableprivate 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 {@Beanpublic 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 {@Beanpublic 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 {@Beanpublic 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@Nullablepublic 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 {@Beanpublic 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 {@Beanpublic 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@Nullablepublic 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@Nullablepublic 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 {@Beanpublic 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;}@Nullableprotected MessageCodesResolver getMessageCodesResolver() {return null;}
}

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

1.2.11 handlerFunctionAdapter 方法

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

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

 1.2.12 mvcConversionService 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {@Beanpublic 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 {@Beanpublic 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;}@Nullableprotected 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 {@Overridepublic boolean supports(Class<?> clazz) {return false;}@Overridepublic void validate(@Nullable Object target, Errors errors) {}}}

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

1.2.14 mvcUriComponentsContributor 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {@Beanpublic 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 {@Beanpublic HttpRequestHandlerAdapter httpRequestHandlerAdapter() {return new HttpRequestHandlerAdapter();}
}

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

1.2.16 simpleControllerHandlerAdapter 方法

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

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

1.2.17 handlerExceptionResolver 方法

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {@Beanpublic 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 {@Beanpublic 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 {@Overrideprotected 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) {}...@Nullabledefault 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 {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {for (WebMvcConfigurer delegate : this.delegates) {delegate.configurePathMatch(configurer);}}...@Overridepublic 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 中只有一个元素或更少实现了该方法,存在多个实现了由返回值方法的对象时直接抛出异常;

http://www.lryc.cn/news/623413.html

相关文章:

  • 项目发布上线清单
  • 如何在Windows系统中更改用户名(中文转英文全流程)
  • LeetCode 837.新 21 点:动态规划+滑动窗口
  • 【运维进阶】实施任务控制
  • C语言---第一个C语言程序
  • 12.web api 3
  • 网格布局 CSS Grid
  • 【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day6
  • k8s集群搭建一主多从的jenkins集群
  • 锂电池SOH预测 | Matlab基于KPCA-PLO-Transformer-LSTM的的锂电池健康状态估计(锂电池SOH预测),附锂电池最新文章汇集
  • 网络原理与编程实战:从 TCP/IP 到 HTTP/HTTPS
  • 《详解 C++ Date 类的设计与实现:从运算符重载到功能测试》
  • KingbaseES:一体化架构与多层防护,支撑业务的持续稳定运行与扩展
  • Manus AI 与多语言手写识别技术剖析
  • 整体设计 之“凝聚式中心点”原型 --整除:智能合约和DBMS的深层联合 之1
  • 第三十九天(WebPack构建打包Mode映射DevTool源码泄漏识别还原)
  • 大模型提示词(Prompt)终极指南:从原理到实战,让AI输出质量提升300%
  • 朝花夕拾(四) --------python中的os库全指南
  • 《算法导论》第 27 章 - 多线程算法
  • -nostartfiles参数官方解释,含义
  • 【远程桌面】从RustDesk服务器看UDP对比WebRTC
  • Rust:实现仅通过索引(序数)导出 DLL 函数的功能
  • Node.js导入MongoDB具体操作
  • Kafka 面试题及详细答案100道(23-35)-- 核心机制2
  • 【前端面试题】前端面试知识点(第三十一题到第六十一题)
  • 计算机毕设选题推荐-基于大数据的全面皮肤病症状数据可视化分析系统【Hadoop、spark、python】
  • day42_2025-08-16
  • ArrayList的contains问题
  • 大模拟 Major
  • 扫地机器人(2025蓝桥杯省A组 H题)