• springboot整合springmvc原理


    springboot的整合其实就是自动配置,springboot是如何实现自动配置springmvc的,先回顾springmvc是做什么的

    springmvc

    工作流程是:请求通过前端控制器将请求URL交给处理器映射器处理获取Handler,并将获取的handler交给处理器适配器执行,执行后返回ModelAndView对象,根据对象值进行页面渲染。

    具体做了什么?

    1、处理请求(请求参数)

    2、处理器映射器、处理器适配器的工作就没有那么明显了

    3、视图解析器

    springboot

    1、配置

      自动配置:AutoConfiguration和Properties

    2、注解

    springboot和springmvc整合

    1、自动配置springmvc

      WebMvcAutoConfiguration、WebMvcProperties

    2、增强springmvc

      https://docs.spring.io/spring-boot/docs/2.3.9.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration

    自动配置在 Spring 的默认值之上添加了以下功能:
    The auto-configuration adds the following features on top of Spring’s defaults:
    包含ContentNegotiatingViewResolver和BeanNameViewResolver视图解析器的bean Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans. 支持静态资源和Webjars Support for serving static resources, including support for WebJars (covered later in this document)).

    自动注册转换器(Converter):页面数据提交到后台转换为对象,
    通用转换器(GenericConverter)
    格式化器(Formatter):可以对日期格式的数据进行格式化,并转换成对象 Automatic registration of Converter, GenericConverter, and Formatter beans.
    HttpMessageConverters:转换请求和响应message,比如对象转换成json字符串 Support for HttpMessageConverters (covered later in this document). 自动注册messagecodes解析器(MessageCodesResolver) 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).

    ContentNegotiatingViewResolver 内容协商视图解析器

    (两次敲击Shift)找到 WebMvcAutoConfiguration , 然后搜索ContentNegotiatingViewResolver,并进入此类中,此类是视图解析,可以看看有没有返回View的方法

        @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) {
                //根据viewName获取View对象
                List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
                //获取优先级高的View对象
                View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
                if (bestView != null) {
                    return bestView;
                }
            }
    .......
        }

    具体步骤:

    1、获取所有实现ViewResolver的视图解析类

    protected void initServletContext(ServletContext servletContext) {
                    // 获取实现ViewResolver接口对象
            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);
                    }
                }
            }
    ... ...
    }

    2、根据视图名获取View对象

    3、根据优先级输出最优View对象

    总结:ContentNegotiatingViewResolver主要是将所有实现ViewResolver接口的类都组合起来,然后根据View Name 获取最优先的返回

    自定义视图解析器

    1、创建实现ViewResolver接口的MyViewResolver类,并交给Spring容器

    @Component
    public class MyViewResolver implements ViewResolver {
    
    
        @Override
        public View resolveViewName(String s, Locale locale) throws Exception {
            return null;
        }
    }

    2、编写Controller

    @RestController
    public class TestController {
    
        @GetMapping("/test")
        public String test(){
            return "test";
        }
    }

    3、查找DispatcherServlet,并在doDispatch打断点

     

    4、debug,访问Controller中的test方法

     

    格式化转换器

            @Bean
            @Override
            public FormattingConversionService mvcConversionService() {
                WebConversionService conversionService = new WebConversionService(this.mvcProperties.getDateFormat());
                addFormatters(conversionService);
                return conversionService;
            }

    进入getDateFormat方法

        public String getDateFormat() {
            return this.dateFormat;
        }
    /**
    * Date format to use. For instance, `dd/MM/yyyy`. 默认的
     */
    private String dateFormat;

    springboot已经做好日期格式的转换了,但是这个日期格式和我们常规的不一样,可以通过配置文件修改

    怎么修改呢

    1、查看WebMvcProperties

     

    2、前缀加属性

     

    发现springboot不推荐使用它,找了一下替代它的

     

            @Bean
            @Override
            public FormattingConversionService mvcConversionService() {
                Format format = this.mvcProperties.getFormat();
                WebConversionService conversionService = new WebConversionService(new DateTimeFormatters()
                        .dateFormat(format.getDate()).timeFormat(format.getTime()).dateTimeFormat(format.getDateTime()));
                addFormatters(conversionService);
                return conversionService;
            }

    测试:

      页面传date类型值(yyyy-MM-dd),

      配置文件中spring.mvc.format.date=yyyy/MM/dd,

      controller的方法参数

        public String test(Date date){}

    结果就会报String转换Date类型失败

    springmvc在springboot框架下扩展

     https://docs.spring.io/spring-boot/docs/2.3.9.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration

    If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without@EnableWebMvc.

    直译:如果您想保留那些 Spring Boot MVC 自定义并进行更多 MVC 自定义(拦截器、格式化程序、视图控制器和其他功能),您可以添加自己的 WebMvcConfigurer 类型的 @Configuration 类,但不添加 @EnableWebMvc。

    自解:想在Spring Boot MVC基础上扩展自定义MVC功能(拦截器、格式化程序、视图控制器和其他功能),可以创建一个实现WebMvcConfigurer接口的类,此类必须标记为配置类(添加@Configuration注解),但是不能添加@EnableWebMvc注解

    If you want to provide custom instances of RequestMappingHandlerMappingRequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.

    如果您想提供 RequestMappingHandlerMapping、RequestMappingHandlerAdapter 或 ExceptionHandlerExceptionResolver 的自定义实例,并且仍然保留 Spring Boot MVC 自定义,您可以声明一个类型为 WebMvcRegistrations 的 bean 并使用它来提供这些组件的自定义实例。

    WebMvcRegistrations需要依赖spring-boot-autoconfigure

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-autoconfigure</artifactId>
            </dependency>

    If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.

    直译:如果您想完全控制 Spring MVC,您可以添加您自己的带有 @EnableWebMvc 注释的 @Configuration,或者添加您自己的 @Configuration-annotated DelegatingWebMvcConfiguration

    自解:想完全重写Spring MVC,可以在自定义类上添加@EnableWebMvc注解

    完全重写Spring MVC的话SpringBoot对SpringMVC的自动配置会完全失效。所有Spring MVC配置都需要自己配置,不推荐使用

    为什么添加@EnableWebMvc注解SpringBoot对SpringMVC的自动配置会完全失效

    @Import(DelegatingWebMvcConfiguration.class)
    public @interface EnableWebMvc {
    }
    public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    @Configuration(proxyBeanMethods = false)
    @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 {
    @ConditionalOnMissingBean(WebMvcConfigurationSupport.class):容器中没有这个组件的时候,自动配置类(WebMvcAutoConfiguration)才生效
  • 相关阅读:
    [Codeup 25482]选美
    [Codeup 25481] swan
    暑假集训D12总结
    [技术]浅谈重载操作符
    2020年寒假第6次学*进度记录
    2020年寒假第5次学*进度记录
    2020年寒假第4次学*进度记录
    “家庭记账本”软件开发(1)
    阅读《梦断代码》随笔(1)
    2020年寒假第三次学*进度记录
  • 原文地址:https://www.cnblogs.com/WarBlog/p/15125059.html
Copyright © 2020-2023  润新知