欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringBoot中SpringMVC自动配置源码学习笔记

程序员文章站 2022-04-19 22:32:05
...

SpringMVC自动配置

源码:
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {

	@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));
		resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
		return resolver;
	}

ContentNegotiatingViewResolver//组合所有的视图解析器的

		源码:
		//视图解析器(根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))
		public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport implements ViewResolver, Ordered, InitializingBean {

			@Override
			@Nullable
			public View resolveViewName(String viewName, Locale locale) throws Exception {
				RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
				Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
				List<MediaType> requestedMediaTypes = getMediaTypes(((ServletRequestAttributes) attrs).getRequest());
				if (requestedMediaTypes != null) {
					//获取候选视图对象
					List<View> candidateViews = getCandidateViews(viewName, locale, requestedMediaTypes);
					//选择最适合的视图对象
					View bestView = getBestView(candidateViews, requestedMediaTypes, attrs);
					if (bestView != null) {
						return bestView;
					}
				}
				
				private List<View> getCandidateViews(String viewName, Locale locale, List<MediaType> requestedMediaTypes) throws Exception {
					List<View> candidateViews = new ArrayList<>();
					if (this.viewResolvers != null) {
						Assert.state(this.contentNegotiationManager != null, "No ContentNegotiationManager set");
						//把所有视图解析器拿来,解析
						for (ViewResolver viewResolver : this.viewResolvers) {
							View view = viewResolver.resolveViewName(viewName, locale);
							if (view != null) {
								candidateViews.add(view);
							}
							for (MediaType requestedMediaType : requestedMediaTypes) {
								List<String> extensions = this.contentNegotiationManager.resolveFileExtensions(requestedMediaType);
								for (String extension : extensions) {
									String viewNameWithExtension = viewName + '.' + extension;
									view = viewResolver.resolveViewName(viewNameWithExtension, locale);
									if (view != null) {
										candidateViews.add(view);
									}
								}
							}
						}
					}
					if (!CollectionUtils.isEmpty(this.defaultViews)) {
						candidateViews.addAll(this.defaultViews);
					}
					return candidateViews;
				}
			}
		}	
		
	//注册国际化功能
	@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;
	}
	
	//初始化方法
	@Override
	protected void initServletContext(ServletContext servletContext) {
		//从容器中获取所有的视图解析器
		Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(obtainApplicationContext(), ViewResolver.class).values();
		//把这个解析器作为要组合的所有的视图解析器
		if (this.viewResolvers == null) {
			this.viewResolvers = new ArrayList<>(matchingBeans.size());
			for (ViewResolver viewResolver : matchingBeans) {
				if (this != viewResolver) {
					this.viewResolvers.add(viewResolver);
				}
			}
		}
		else {
			for (int i = 0; i < this.viewResolvers.size(); i++) {
				ViewResolver vr = this.viewResolvers.get(i);
				if (matchingBeans.contains(vr)) {
					continue;
				}
				String name = vr.getClass().getName() + i;
				obtainApplicationContext().getAutowireCapableBeanFactory().initializeBean(vr, name);
			}
		}
		AnnotationAwareOrderComparator.sort(this.viewResolvers);
		this.cnmFactoryBean.setServletContext(servletContext);
	}
	
	//添加格式化器,自己添加的格式化器转换器,我们只需要放在容器中即可
	@Override
	public void addFormatters(FormatterRegistry registry) {
		//Converter转换器,类型转换
		for (Converter<?, ?> converter : getBeansOfType(Converter.class)) {
			registry.addConverter(converter);
		}
		for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {
			registry.addConverter(converter);
		}
		//Formatter格式化器,日期
		for (Formatter<?> formatter : getBeansOfType(Formatter.class)) {
			registry.addFormatter(formatter);
		}
	}
	private <T> Collection<T> getBeansOfType(Class<T> type) {
		//从容器beanFactory中获取所有的Converter
		return this.beanFactory.getBeansOfType(type).values();
	}
	
	@Configuration
	@Import(EnableWebMvcConfiguration.class)
	@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
	@Order(0)
	public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
	
		private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;
		
		//是HttpMessageConverters从容器中确定;获取所有的HttpMessageConverter
		public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties,
			ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider,
			ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) {
			this.resourceProperties = resourceProperties;
			this.mvcProperties = mvcProperties;
			this.beanFactory = beanFactory;
			this.messageConvertersProvider = messageConvertersProvider;
			this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
		}
	}	

HttpMessageConverters//是HttpMessageConverters从容器中确定;获取所有的HttpMessageConverter

		源码:
		public class HttpMessageConverters implements Iterable<HttpMessageConverter<?>> {
			
			public HttpMessageConverters(Collection<HttpMessageConverter<?>> additionalConverters) {
				this(true, additionalConverters);
			}
		}
	
	
	//消息解析,从配置类里拿配置
	@Override
	public MessageCodesResolver getMessageCodesResolver() {
		if (this.mvcProperties.getMessageCodesResolverFormat() != null) {
			DefaultMessageCodesResolver resolver = new DefaultMessageCodesResolver();
			resolver.setMessageCodeFormatter(this.mvcProperties.getMessageCodesResolverFormat());
			return resolver;
		}
		return null;
	}

getMessageCodesResolverFormat()

		源码:
		@ConfigurationProperties(prefix = "spring.mvc")
		public class WebMvcProperties {
		
			private DefaultMessageCodesResolver.Format messageCodesResolverFormat;
			
			public DefaultMessageCodesResolver.Format getMessageCodesResolverFormat() {
				return this.messageCodesResolverFormat;
			}
		}

DefaultMessageCodesResolver

			源码:
			@SuppressWarnings("serial")
			public class DefaultMessageCodesResolver implements MessageCodesResolver, Serializable {
				
				//定义错误代码生成规则
				public enum Format implements MessageCodeFormatter {
					/**
					 * Prefix the error code at the beginning of the generated message code. e.g.:
					 * {@code errorCode + "." + object name + "." + field}
					 * 第一种规则(错误代码,对象名,属性名)
					 */					
					PREFIX_ERROR_CODE {
						@Override
						public String format(String errorCode, @Nullable String objectName, @Nullable String field) {
							return toDelimitedString(errorCode, objectName, field);
						}
					},

					/**
					 * Postfix the error code at the end of the generated message code. e.g.:
					 * {@code object name + "." + field + "." + errorCode}
					 * 第二种规则(对象名,属性名,错误代码)
					 */
					POSTFIX_ERROR_CODE {
						@Override
						public String format(String errorCode, @Nullable String objectName, @Nullable String field) {
							return toDelimitedString(objectName, field, errorCode);
						}
					};

					/**
					 * Concatenate the given elements, delimiting each with
					 * {@link DefaultMessageCodesResolver#CODE_SEPARATOR}, skipping zero-length or
					 * null elements altogether.
					 */
					public static String toDelimitedString(String... elements) {
						StringBuilder rtn = new StringBuilder();
						for (String element : elements) {
							if (StringUtils.hasLength(element)) {
								rtn.append(rtn.length() == 0 ? "" : CODE_SEPARATOR);
								rtn.append(element);
							}
						}
						return rtn.toString();
					}
				}			
			}
	//可以配置一个ConfigurableWebBindingInitializer来替换默认的(添加到容器中)
	@Override
	protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
		try {
			return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);
		}
		catch (NoSuchBeanDefinitionException ex) {
			return super.getConfigurableWebBindingInitializer();
		}
	}

getConfigurableWebBindingInitializer()

		源码:
		//初始化web数据绑定器(WebDataBinder)的,把请求数据绑定到哪,比如到JavaBean
		protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
			ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
			initializer.setConversionService(mvcConversionService());
			initializer.setValidator(mvcValidator());
			MessageCodesResolver messageCodesResolver = getMessageCodesResolver();
			if (messageCodesResolver != null) {
				initializer.setMessageCodesResolver(messageCodesResolver);
			}
			return initializer;
		}

ConfigurableWebBindingInitializer

			源码:
			//初始化web数据绑定器
			public class ConfigurableWebBindingInitializer implements org.springframework.web.bind.support.WebBindingInitializer {
				@Override
				public void initBinder(WebDataBinder binder) {
					binder.setAutoGrowNestedPaths(this.autoGrowNestedPaths);
					if (this.directFieldAccess) {
						binder.initDirectFieldAccess();
					}
					if (this.messageCodesResolver != null) {
						binder.setMessageCodesResolver(this.messageCodesResolver);
					}
					if (this.bindingErrorProcessor != null) {
						binder.setBindingErrorProcessor(this.bindingErrorProcessor);
					}
					if (this.validator != null && binder.getTarget() != null &&
							this.validator.supports(binder.getTarget().getClass())) {
						binder.setValidator(this.validator);
					}
					if (this.conversionService != null) {
						binder.setConversionService(this.conversionService);
					}
					if (this.propertyEditorRegistrars != null) {
						for (PropertyEditorRegistrar propertyEditorRegistrar : this.propertyEditorRegistrars) {
							propertyEditorRegistrar.registerCustomEditors(binder);
						}
					}
				}			
			}
}

DispatcherServlet

	源码:
	@SuppressWarnings("serial")
	public class DispatcherServlet extends FrameworkServlet {
		
		//所有请求进来调用该方法
		protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
			HttpServletRequest processedRequest = request;
			HandlerExecutionChain mappedHandler = null;
			boolean multipartRequestParsed = false;

			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

			try {
				ModelAndView mv = null;
				Exception dispatchException = null;

				try {
					processedRequest = checkMultipart(request);
					multipartRequestParsed = (processedRequest != request);

					// Determine handler for the current request.
					mappedHandler = getHandler(processedRequest);
					if (mappedHandler == null) {
						noHandlerFound(processedRequest, response);
						return;
					}

					// Determine handler adapter for the current request.
					HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

					// Process last-modified header, if supported by the handler.
					String method = request.getMethod();
					boolean isGet = "GET".equals(method);
					if (isGet || "HEAD".equals(method)) {
						long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
						if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
							return;
						}
					}

					if (!mappedHandler.applyPreHandle(processedRequest, response)) {
						return;
					}

					// Actually invoke the handler.
					mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

					if (asyncManager.isConcurrentHandlingStarted()) {
						return;
					}

					applyDefaultViewName(processedRequest, mv);
					mappedHandler.applyPostHandle(processedRequest, response, mv);
				}
				catch (Exception ex) {
					dispatchException = ex;
				}
				catch (Throwable err) {
					// As of 4.3, we're processing Errors thrown from handler methods as well,
					// making them available for @ExceptionHandler methods and other scenarios.
					dispatchException = new NestedServletException("Handler dispatch failed", err);
				}
				processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
			}
			catch (Exception ex) {
				triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
			}
			catch (Throwable err) {
				triggerAfterCompletion(processedRequest, response, mappedHandler,
						new NestedServletException("Handler processing failed", err));
			}
			finally {
				if (asyncManager.isConcurrentHandlingStarted()) {
					// Instead of postHandle and afterCompletion
					if (mappedHandler != null) {
						mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
					}
				}
				else {
					// Clean up any resources used by a multipart request.
					if (multipartRequestParsed) {
						cleanupMultipart(processedRequest);
					}
				}
			}
		}				
	}
相关标签: spring boot