16 SpringMVC自动配置原理

  • 官方文档
https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications

SpringBoot对SpringMVC的默认配置:(WebMvcAutoConfiguration)

1 Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

ContentNegotiatingViewResolver:组合所有的视图解析器的
在容器中添加一个视图解析器;ContentNegotiatingViewResolver会自动的将其组合进来
  • WebMvcAutoConfiguration.class
// 向容器中添加视图解析器组件
@Bean
@ConditionalOnBean({ViewResolver.class})
@ConditionalOnMissingBean(
	name = {"viewResolver"},
	value = {ContentNegotiatingViewResolver.class}
)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
	// ContentNegotiatingViewResolver: 组合所有的视图解析器
	ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
	resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
	resolver.setOrder(-2147483648);
	return resolver;
}
  • ContentNegotiatingViewResolver.class
@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 = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());
	if (requestedMediaTypes != null) {
		// 获取候选的试图对象
		List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
		
		// 选择一个最适合的试图对象返回
		View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
		if (bestView != null) {
			return bestView;
		}
	}

	String mediaTypeInfo = this.logger.isDebugEnabled() && requestedMediaTypes != null ? " given " + requestedMediaTypes.toString() : "";
	if (this.useNotAcceptableStatusCode) {
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Using 406 NOT_ACCEPTABLE" + mediaTypeInfo);
		}

		return NOT_ACCEPTABLE_VIEW;
	} else {
		this.logger.debug("View remains unresolved" + mediaTypeInfo);
		return null;
	}
}
  • ContentNegotiatingViewResolver.class----getCandidateViews()
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");
		Iterator var5 = this.viewResolvers.iterator();

		while(var5.hasNext()) {
			ViewResolver viewResolver = (ViewResolver)var5.next();
			View view = viewResolver.resolveViewName(viewName, locale);
			if (view != null) {
				candidateViews.add(view);
			}

			Iterator var8 = requestedMediaTypes.iterator();

			while(var8.hasNext()) {
				MediaType requestedMediaType = (MediaType)var8.next();
				List<String> extensions = this.contentNegotiationManager.resolveFileExtensions(requestedMediaType);
				Iterator var11 = extensions.iterator();

				while(var11.hasNext()) {
					String extension = (String)var11.next();
					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;
}
  • ContentNegotiatingViewResolver.class----initServletContext
protected void initServletContext(ServletContext servletContext) {
	// 初始化方法,使用BeanFactoryUtils获取所有的视图解析器(ViewResolver)
	Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
	
	ViewResolver viewResolver;
	
	// 将所有的视图解析器放入this.viewResolvers
	if (this.viewResolvers == null) {
		this.viewResolvers = new ArrayList(matchingBeans.size());
		Iterator var3 = matchingBeans.iterator();

		while(var3.hasNext()) {
			viewResolver = (ViewResolver)var3.next();
			if (this != viewResolver) {
				this.viewResolvers.add(viewResolver);
			}
		}
	} else {
		for(int i = 0; i < this.viewResolvers.size(); ++i) {
			viewResolver = (ViewResolver)this.viewResolvers.get(i);
			if (!matchingBeans.contains(viewResolver)) {
				String name = viewResolver.getClass().getName() + i;
				this.obtainApplicationContext().getAutowireCapableBeanFactory().initializeBean(viewResolver, name);
			}
		}
	}

	AnnotationAwareOrderComparator.sort(this.viewResolvers);
	this.cnmFactoryBean.setServletContext(servletContext);
}
1.1 测试
1.1.1 自定义视图解析器
package com.gp6.springboot16;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;

import java.util.Locale;

@SpringBootApplication
public class Springboot16Application {

    public static void main(String[] args) {
        SpringApplication.run(Springboot16Application.class, args);
    }

    @Bean
    public ViewResolver myViewResolver(){
        return new MyViewResolver();
    }

    public static class MyViewResolver implements ViewResolver{

        @Override
        public View resolveViewName(String viewName, Locale locale) throws Exception {
            return null;
        }
    }
}

1.1.2 测试步骤
1: 在DispatcherServlet.class中doDispatch()前打上断点
2: 启动项目
3: 访问http://localhost:8080/
1.1.2 测试结果

测试结果

其余配置请在SpringMVC框架中学习

2 Support for serving static resources, including support for WebJars (see below)
静态资源文件夹路径和webjars
3 Static index.html support.
静态首页访问
4 Custom Favicon support (see below).
自定义图标: favicon.ico
5 自动注册 of Converter, GenericConverter, Formatter beans.
Converter:转换器
Formatter: 格式化器
6 Support for HttpMessageConverters (see below).
HttpMessageConverter:SpringMVC用来转换Http请求和响应
HttpMessageConverters` 是从容器中确定;获取所有的HttpMessageConverter;

7 Automatic registration of MessageCodesResolver (see below).
定义错误代码生成规则
8 Automatic use of a ConfigurableWebBindingInitializer bean (see below).
配置一个ConfigurableWebBindingInitializer来替换默认的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值