11、框架-SpringBoot-SpringMVC自动配置

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_40871734/article/details/100025380

在进行测试前,我们还需要知道一个东西,就是SpringBoot 对SpringMVC还做了哪些配置,包括如何扩展,如何定制。只有把这些都搞清楚了,在之后使用才会更加得心应手。

途径一:源码分析
途径二:官方文档

地址 : https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-developing-web-applications.html

我们来阅读一段官方文档:

29.1.1 Spring MVC Auto-configuration
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.

The auto-configuration adds the following features on top of Spring’s defaults:

//包含视图解析器
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
//支持静态资源文件夹的路径,以及webjars
Support for serving static resources, including support for WebJars (covered later in this document)).
//自动注册了Converter:【转换器,这就是我们网页提交数据到后台自动封装成为对象的东西,比如把18字符串自动转换为int类型】
//Formatter:【格式化器,比如页面给我们了一个2019-8-10,它会给我们自动格式化为Date对象】
Automatic registration of Converter, GenericConverter, and Formatter beans.
//HttpMessageConverters:SpringMVC用来转换Http请求和响应的的,比如我们要把一个User对象转换为JSON字符串,可以去看官网文档解释;
Support for HttpMessageConverters (covered later in this document).
//定义错误代码生成规则的
Automatic registration of MessageCodesResolver (covered later in this document).
//首页定制
Static index.html support.
//图标定制
Custom Favicon support (covered later in this document).
//初始化数据绑定器:帮我们把请求数据绑定到JavaBean中!
Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).

If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.

来仔细对照看一下它怎么实现的,它告诉我们SpringBoot已经帮我们自动配置好了SpringMVC,自动配置了哪些东西呢?

ContentNegotiatingViewResolver

自动配置了ViewResolver,就是我们之前学习的SpringMVC的视图解析器:即根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。去看看这里的源码:找到 WebMvcAutoConfiguration , 然后搜索ContentNegotiatingViewResolver。找到如下方法:

 @Bean //我们在这里确实看到已经给容器中注册了一个bean
        @ConditionalOnBean({ViewResolver.class})
        @ConditionalOnMissingBean(
            name = {"viewResolver"},
            value = {ContentNegotiatingViewResolver.class}
        )
        public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
            ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
            resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
            resolver.setOrder(-2147483648);
            return resolver;
        }

点进此类,找到对应的解析视图的代码

注解说明:@Nullable 即参数可为null

@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;
        }
    }

继续点进去看,它是怎么获得候选的视图的? 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());

既然它是在容器中去找视图解析器,是否可以猜想,我们就可以去实现定制了?

我们可以自己给容器中去添加一个视图解析器;这个类就会帮我们自动的将它组合进来;去实现一下

在自己的主程序中去写一个视图解析器来试试;

@Bean //放到bean中
    public ViewResolver myViewResolver(){
        return new MyViewResolver();
    }

    //写一个静态内部类,视图解析器就需要实现ViewResolver接口
    private static class MyViewResolver implements ViewResolver{
        @Override
        public View resolveViewName(String s, Locale locale) throws Exception {
            return null;
        }
    }

怎么看自己写的视图解析器有没有起作用呢?给dispatcherServlet中的 doDispatch方法加个断点进行调试一下,因为所有的请求都会走到这个方法中
在这里插入图片描述
启动项目,然后随便访问一个页面,看一下Debug信息;

找到this;
在这里插入图片描述
找到视图解析器,看到自己定义的就在这里了;
在这里插入图片描述
所以说,如果想要使用自己定制化的东西,只需要给容器中添加这个组件就好了!剩下的事情SpringBoot就会帮我们做了

转换器和格式化器

找到格式化转换器

@Bean
        public FormattingConversionService mvcConversionService() {
            //拿到配置文件中的格式化规则
            WebConversionService conversionService = new WebConversionService(this.mvcProperties.getDateFormat());
            this.addFormatters(conversionService);
            return conversionService;
        }

点进去

 public String getDateFormat() {
        return this.dateFormat;
    }

可以看到在Properties文件中,可以自动配置它,如果注册了自己的格式化方式,就会注册到Bean中,否则不会注册

我们可以在配置文件中配置日期格式化的规则:
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40871734/article/details/100025380