springboot源码解析autoconfigure之WebMvcAutoConfiguration
生活随笔
收集整理的這篇文章主要介紹了
springboot源码解析autoconfigure之WebMvcAutoConfiguration
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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的全部內容,希望文章能夠幫你解決所遇到的問題。