• SpringBoot:MVC自动配置原理


    经阅读官方技术文档及其源码,SpringBoot为spring mvc提供了自动配置,它可以很好地与大多数应用程序一起工作。

    自动配置在Spring默认设置的基础上添加了以下功能:
    1、 包含视图解析器
    2、 支持静态资源文件夹的路径,以及webjars
    3、自动注册了Converter:
    转换器,这就是我们网页提交数据到后台自动封装成为对象的东西,比如把"1"字符串自动转换为int类型
    4、SpringMVC用来转换Http请求和响应的的,比如我们要把一个User对象转换为JSON字符串,可以去看官网文档解释;
    // 定义错误代码生成规则的
    // 首页定制
    // 图标定制
    // 初始化数据绑定器:帮我们把请求数据绑定到JavaBean中!

    如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(拦截器、格式化程序、视图控制器和其他功能),则可以添加自己
    的@configuration类,类型为webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供
    RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义
    实例,则可以声明WebMVCregistrationAdapter实例来提供此类组件。

    ContentNegotiatingViewResolver 内容协商视图解析器
    自动配置了ViewResolver,就是之前学习的SpringMVC的视图解析器;

    即根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。

    源码:找到 WebMvcAutoConfiguration , 然后搜索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使用所有其他视图解析器来定位视图,因此它应该具有较高的优先级
        resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return resolver;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    找到对应的解析视图的代码:

    @Nullable // 注解说明:@Nullable 即参数可为null
    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;
            }
        }
        // .....
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    是怎么获得候选的视图的呢?

    getCandidateViews中看到他是把所有的视图解析器拿来,进行while循环,挨个解析!

    Iterator var5 = this.viewResolvers.iterator();
    所以得出结论:ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的

    属性viewResolvers:

    
    protected void initServletContext(ServletContext servletContext) {
        // 这里它是从beanFactory工具中获取容器中的所有视图解析器
        // ViewRescolver.class 把所有的视图解析器来组合的
        Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
        ViewResolver viewResolver;
        if (this.viewResolvers == null) {
            this.viewResolvers = new ArrayList(matchingBeans.size());
        }
        // ...............
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    Qt之延时总结
    Python SSL操作手册
    Java数据结构第二课 —— 泛型(1)
    webRTC H265浏览器播放器+metaRTC推流实现webRTC H265解决方案
    论文笔记: 数据驱动的地震波形反演--健壮性与泛化性研究
    vue3 迫不得已我硬着头皮查看了keepalive的源代码,解决了线上的问题
    调节扬声器和麦克风的音量
    文件操作~
    【云原生】Docker网络
    考柏的感慨
  • 原文地址:https://blog.csdn.net/yooppa/article/details/126425548