2019独角兽企业重金招聘Python工程师标准>>>

说在前面

本次开始spring-boot-autoconfigure源码解析之WebMvcAutoConfiguration

源码解析

@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,WebMvcConfigurerAdapter.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {public static final String DEFAULT_PREFIX = "";public static final String DEFAULT_SUFFIX = "";@Bean@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {return new OrderedHiddenHttpMethodFilter();}@Bean@ConditionalOnMissingBean(HttpPutFormContentFilter.class)@ConditionalOnProperty(prefix = "spring.mvc.formcontent.putfilter", name = "enabled", matchIfMissing = true)public OrderedHttpPutFormContentFilter httpPutFormContentFilter() {return new OrderedHttpPutFormContentFilter();}// Defined as a nested config to ensure WebMvcConfigurerAdapter is not read when not 定义为嵌套配置,以确保不读取WebMvcConfigurerAdapter// on the classpath 在类路径中@Configuration@Import(EnableWebMvcConfiguration.class)@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })public static class WebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter {private static final Log logger = LogFactory.getLog(WebMvcConfigurerAdapter.class);private final ResourceProperties resourceProperties;private final WebMvcProperties mvcProperties;private final ListableBeanFactory beanFactory;private final HttpMessageConverters messageConverters;final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties,WebMvcProperties mvcProperties, ListableBeanFactory beanFactory,@Lazy HttpMessageConverters messageConverters,ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) {this.resourceProperties = resourceProperties;this.mvcProperties = mvcProperties;this.beanFactory = beanFactory;this.messageConverters = messageConverters;this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();}@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.addAll(this.messageConverters.getConverters());}@Overridepublic void configureAsyncSupport(AsyncSupportConfigurer configurer) {Long timeout = this.mvcProperties.getAsync().getRequestTimeout();if (timeout != null) {configurer.setDefaultTimeout(timeout);}}@Overridepublic void configureContentNegotiation(ContentNegotiationConfigurer configurer) {Map<String, MediaType> mediaTypes = this.mvcProperties.getMediaTypes();for (Entry<String, MediaType> mediaType : mediaTypes.entrySet()) {configurer.mediaType(mediaType.getKey(), mediaType.getValue());}}//    初始化InternalResourceViewResolver@Bean@ConditionalOnMissingBeanpublic InternalResourceViewResolver defaultViewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix(this.mvcProperties.getView().getPrefix());resolver.setSuffix(this.mvcProperties.getView().getSuffix());return resolver;}//    初始化BeanNameViewResolver@Bean@ConditionalOnBean(View.class)@ConditionalOnMissingBeanpublic BeanNameViewResolver beanNameViewResolver() {BeanNameViewResolver resolver = new BeanNameViewResolver();resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);return resolver;}//    初始化ContentNegotiatingViewResolver@Bean@ConditionalOnBean(ViewResolver.class)@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class));// ContentNegotiatingViewResolver uses all the other view resolvers to locate contentatingviewresolver使用所有其他视图解析器来定位// a view so it should have a high precedence 一个视图,因此它应该具有较高的优先级resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);return resolver;}@Bean@ConditionalOnMissingBean@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")public LocaleResolver localeResolver() {if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {return new FixedLocaleResolver(this.mvcProperties.getLocale());}AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();localeResolver.setDefaultLocale(this.mvcProperties.getLocale());return localeResolver;}@Bean@ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")public Formatter<Date> dateFormatter() {return new DateFormatter(this.mvcProperties.getDateFormat());}@Overridepublic MessageCodesResolver getMessageCodesResolver() {if (this.mvcProperties.getMessageCodesResolverFormat() != null) {DefaultMessageCodesResolver resolver = new DefaultMessageCodesResolver();resolver.setMessageCodeFormatter(this.mvcProperties.getMessageCodesResolverFormat());return resolver;}return null;}@Overridepublic void addFormatters(FormatterRegistry registry) {for (Converter<?, ?> converter : getBeansOfType(Converter.class)) {registry.addConverter(converter);}for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {registry.addConverter(converter);}for (Formatter<?> formatter : getBeansOfType(Formatter.class)) {registry.addFormatter(formatter);}}private <T> Collection<T> getBeansOfType(Class<T> type) {return this.beanFactory.getBeansOfType(type).values();}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {if (!this.resourceProperties.isAddMappings()) {logger.debug("Default resource handling disabled");return;}Integer cachePeriod = this.resourceProperties.getCachePeriod();if (!registry.hasMappingForPattern("/webjars/**")) {customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(cachePeriod));}String staticPathPattern = this.mvcProperties.getStaticPathPattern();if (!registry.hasMappingForPattern(staticPathPattern)) {customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern).addResourceLocations(this.resourceProperties.getStaticLocations()).setCachePeriod(cachePeriod));}}@Beanpublic WelcomePageHandlerMapping welcomePageHandlerMapping(ResourceProperties resourceProperties) {return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage(),this.mvcProperties.getStaticPathPattern());}private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) {if (this.resourceHandlerRegistrationCustomizer != null) {this.resourceHandlerRegistrationCustomizer.customize(registration);}}@Bean@ConditionalOnMissingBean({ RequestContextListener.class,RequestContextFilter.class })public static RequestContextFilter requestContextFilter() {return new OrderedRequestContextFilter();}@Configuration@ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)public static class FaviconConfiguration {private final ResourceProperties resourceProperties;public FaviconConfiguration(ResourceProperties resourceProperties) {this.resourceProperties = resourceProperties;}//       初始化SimpleUrlHandlerMapping@Beanpublic SimpleUrlHandlerMapping faviconHandlerMapping() {SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",faviconRequestHandler()));return mapping;}@Beanpublic ResourceHttpRequestHandler faviconRequestHandler() {ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();requestHandler.setLocations(this.resourceProperties.getFaviconLocations());return requestHandler;}}}/*** Configuration equivalent to {@code @EnableWebMvc}.*/@Configurationpublic static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {private final WebMvcProperties mvcProperties;private final ListableBeanFactory beanFactory;private final WebMvcRegistrations mvcRegistrations;public EnableWebMvcConfiguration(ObjectProvider<WebMvcProperties> mvcPropertiesProvider,ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider,ListableBeanFactory beanFactory) {this.mvcProperties = mvcPropertiesProvider.getIfAvailable();this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();this.beanFactory = beanFactory;}//    创建RequestMappingHandlerAdapter@Bean@Overridepublic RequestMappingHandlerAdapter requestMappingHandlerAdapter() {RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();adapter.setIgnoreDefaultModelOnRedirect((this.mvcProperties != null)? this.mvcProperties.isIgnoreDefaultModelOnRedirect() : true);return adapter;}@Overrideprotected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {if (this.mvcRegistrations != null&& this.mvcRegistrations.getRequestMappingHandlerAdapter() != null) {return this.mvcRegistrations.getRequestMappingHandlerAdapter();}return super.createRequestMappingHandlerAdapter();}//    创建RequestMappingHandlerMapping@Bean@Primary@Overridepublic RequestMappingHandlerMapping requestMappingHandlerMapping() {// Must be @Primary for MvcUriComponentsBuilder to workreturn super.requestMappingHandlerMapping();}//    创建Validator@Bean@Overridepublic Validator mvcValidator() {if (!ClassUtils.isPresent("javax.validation.Validator",getClass().getClassLoader())) {return super.mvcValidator();}return WebMvcValidator.get(getApplicationContext(), getValidator());}@Overrideprotected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {if (this.mvcRegistrations != null&& this.mvcRegistrations.getRequestMappingHandlerMapping() != null) {return this.mvcRegistrations.getRequestMappingHandlerMapping();}return super.createRequestMappingHandlerMapping();}@Overrideprotected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {try {return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);}catch (NoSuchBeanDefinitionException ex) {return super.getConfigurableWebBindingInitializer();}}@Overrideprotected ExceptionHandlerExceptionResolver createExceptionHandlerExceptionResolver() {if (this.mvcRegistrations != null && this.mvcRegistrations.getExceptionHandlerExceptionResolver() != null) {return this.mvcRegistrations.getExceptionHandlerExceptionResolver();}return super.createExceptionHandlerExceptionResolver();}@Overrideprotected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {super.configureHandlerExceptionResolvers(exceptionResolvers);if (exceptionResolvers.isEmpty()) {addDefaultHandlerExceptionResolvers(exceptionResolvers);}if (this.mvcProperties.isLogResolvedException()) {for (HandlerExceptionResolver resolver : exceptionResolvers) {if (resolver instanceof AbstractHandlerExceptionResolver) {((AbstractHandlerExceptionResolver) resolver).setWarnLogCategory(resolver.getClass().getName());}}}}//     创建ContentNegotiationManager@Bean@Overridepublic ContentNegotiationManager mvcContentNegotiationManager() {ContentNegotiationManager manager = super.mvcContentNegotiationManager();List<ContentNegotiationStrategy> strategies = manager.getStrategies();ListIterator<ContentNegotiationStrategy> iterator = strategies.listIterator();while (iterator.hasNext()) {ContentNegotiationStrategy strategy = iterator.next();if (strategy instanceof PathExtensionContentNegotiationStrategy) {iterator.set(new OptionalPathExtensionContentNegotiationStrategy(strategy));}}return manager;}}@Configuration@ConditionalOnEnabledResourceChainstatic class ResourceChainCustomizerConfiguration {@Beanpublic ResourceChainResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer() {return new ResourceChainResourceHandlerRegistrationCustomizer();}}interface ResourceHandlerRegistrationCustomizer {void customize(ResourceHandlerRegistration registration);}private static class ResourceChainResourceHandlerRegistrationCustomizerimplements ResourceHandlerRegistrationCustomizer {@Autowiredprivate ResourceProperties resourceProperties = new ResourceProperties();@Overridepublic void customize(ResourceHandlerRegistration registration) {ResourceProperties.Chain properties = this.resourceProperties.getChain();configureResourceChain(properties,registration.resourceChain(properties.isCache()));}private void configureResourceChain(ResourceProperties.Chain properties,ResourceChainRegistration chain) {Strategy strategy = properties.getStrategy();if (strategy.getFixed().isEnabled() || strategy.getContent().isEnabled()) {chain.addResolver(getVersionResourceResolver(strategy));}if (properties.isGzipped()) {chain.addResolver(new GzipResourceResolver());}if (properties.isHtmlApplicationCache()) {chain.addTransformer(new AppCacheManifestTransformer());}}private ResourceResolver getVersionResourceResolver(ResourceProperties.Strategy properties) {VersionResourceResolver resolver = new VersionResourceResolver();if (properties.getFixed().isEnabled()) {String version = properties.getFixed().getVersion();String[] paths = properties.getFixed().getPaths();resolver.addFixedVersionStrategy(version, paths);}if (properties.getContent().isEnabled()) {String[] paths = properties.getContent().getPaths();resolver.addContentVersionStrategy(paths);}return resolver;}}static final class WelcomePageHandlerMapping extends AbstractUrlHandlerMapping {private static final Log logger = LogFactory.getLog(WelcomePageHandlerMapping.class);private WelcomePageHandlerMapping(Resource welcomePage,String staticPathPattern) {if (welcomePage != null && "/**".equals(staticPathPattern)) {logger.info("Adding welcome page: " + welcomePage);ParameterizableViewController controller = new ParameterizableViewController();
//          WelcomePageHandlerMapping直接转发index.htmlcontroller.setViewName("forward:index.html");setRootHandler(controller);setOrder(0);}}@Overridepublic Object getHandlerInternal(HttpServletRequest request) throws Exception {for (MediaType mediaType : getAcceptedMediaTypes(request)) {if (mediaType.includes(MediaType.TEXT_HTML)) {return super.getHandlerInternal(request);}}return null;}private List<MediaType> getAcceptedMediaTypes(HttpServletRequest request) {String acceptHeader = request.getHeader(HttpHeaders.ACCEPT);return MediaType.parseMediaTypes(StringUtils.hasText(acceptHeader) ? acceptHeader : "*/*");}}/*** Decorator to make {@link PathExtensionContentNegotiationStrategy} optional* depending on a request attribute.*/static class OptionalPathExtensionContentNegotiationStrategyimplements ContentNegotiationStrategy {private static final String SKIP_ATTRIBUTE = PathExtensionContentNegotiationStrategy.class.getName() + ".SKIP";private final ContentNegotiationStrategy delegate;OptionalPathExtensionContentNegotiationStrategy(ContentNegotiationStrategy delegate) {this.delegate = delegate;}@Overridepublic List<MediaType> resolveMediaTypes(NativeWebRequest webRequest)throws HttpMediaTypeNotAcceptableException {Object skip = webRequest.getAttribute(SKIP_ATTRIBUTE,RequestAttributes.SCOPE_REQUEST);if (skip != null && Boolean.parseBoolean(skip.toString())) {return Collections.emptyList();}return this.delegate.resolveMediaTypes(webRequest);}}}

说在最后

本次仅代表个人观点,仅供参考。

转载于:https://my.oschina.net/u/3775437/blog/3029550

springboot源码解析autoconfigure之WebMvcAutoConfiguration相关推荐

  1. springboot源码解析-管中窥豹系列之BeanFactoryPostProcessor(十一)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  2. SpringBoot源码解析

    SpringBoot源码解析 1.启动的过程: 首先在main函数中启动当前应用程序(SpringApplication启动) 创建SpringApplication对象(new SpringAppl ...

  3. maven 公共模块依赖_「spring-boot 源码解析」spring-boot 依赖管理

    问题 maven 工程,依赖管理是非常基本又非常重要的功能,现在的工程越来越庞大,依赖越来越多,各种二方包.三方包太多太多,依赖冲突处理起来真是让人头疼,经常需要涉及到多个地方需要调整. 微信公众号: ...

  4. 【java】spring-boot源码解析之应用启动

    spring boot 项目使用默认配置的思想,极大的简化了 spring 项目的开发.下面的代码就是一个最简单的 spring 项目: @SpringBootApplication public c ...

  5. SpringBoot源码解析(十一)@Primary

    在SpringBoot中有许多类使用到了@Primary注解,关于用法,请看这篇博客:在spring中常被忽视的注解 @Primary. 这次我们不说用法,从源码层面来看下: 一.入口 在创建bean ...

  6. SpringBoot 源码解析——如何进行源码环境调试?

    已经分析过 spring-boot-tests/spring-boot-smoke-tests 下的冒烟测试和很早之前版本的 sample 是一样的,所以我们想直接利用这些 sample code 来 ...

  7. spring-boot源码解析之AnnotationConfigServletWebServerApplicationContext

    文章目录 主要功能 Factory Constructor Additional Component Candidates Parent Class ServletWebServerApplicati ...

  8. SpringBoot源码解析(七)EnvironmentPostProcessor

    本文将重点介绍SpringBoot提供给我们的另一个扩展点EnvironmentPostProcessor,它允许我们到任意的指定目录.以任意的方式加载一组配置,并赋予任意的优先级 上文对prepar ...

  9. SpringBoot 源码解析 —— SpringApplication 源码分析

    正常的 SpringBoot 应用程序 一个正常的 SpringBoot 项目的启动类中常见代码如下: @SpringBootApplication public class SpringbotApp ...

最新文章

  1. 细鹏系列裸金属服务器多核算力,鲲鹏凌云,开启多元计算新架构_外发版(40页)-原创力文档...
  2. [Mongodb]删除指定字段
  3. BZOJ2568 [国家集训队2012]比特集合
  4. 数据库-优化-索引-索引的优化注意事项
  5. centos内核参数调优
  6. 编译Linux版本飞鸽传书的不完全解决办法
  7. 关于sha1加密的一个问题。。。。
  8. Bootstrap 标签导航的布局
  9. 怎么把一张暗的照片调亮_拍摄一张好照片有哪些步骤?看完这篇实操文章你就懂了...
  10. GPUImage相关(转)
  11. fastboot刷系统的步骤
  12. pandas groupby 数据丢失问题
  13. java zhs16gbk_oracle 修改字符集 为ZHS16GBK
  14. java lang runtime_android – java.lang.RuntimeException:无法启动...
  15. 蓬莱小课:HR问“你的职业规划是什么”,这样回答90%不出错
  16. Java课程设计——计算平面图形面积周长、立体图形体积
  17. Unity 灯光系统
  18. 计算机专业江苏考研,22考研,计算机专业江苏地区有哪些性价比高又好考的学校,快收藏吧!...
  19. 如何判断是不是个maven项目
  20. win7 下anaconda 安装及安装包

热门文章

  1. 淘宝大秒系统设计详解 | 许令波
  2. 让开发自动化持续重构 --使用静态分析工具识别代码味道
  3. Java快速扫盲指南
  4. 《JAVA与模式》之工厂方法模式
  5. Python配置OpenCV时报错:ImportError DLL load failed: %1 不是有效的 Win32 应用程序
  6. C++和MATLAB混合编程-DLL篇
  7. 有趣、好玩、有料的网站收藏
  8. Python基础教程(九):面向对象、正则表达式
  9. 信息系统项目管理师-常用术语中英文对应
  10. 4.从单应矩阵中分离得到内参和外参(需要拍摄n=3张标定图片)