SpringBoot学习-SpringMVC自动配置

SpringBoot学习-SpringMVC自动配置

前言

在SpringBoot官网对于SpringMVCde 自动配置介绍

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.
  • Support for serving static resources, including support for WebJars (covered later in this document)).
  • Automatic registration of ConverterGenericConverter, and Formatter beans.
  • 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).
  • 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 RequestMappingHandlerMappingRequestMappingHandlerAdapter, 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.

2-谷歌翻译如下

Spring MVC自动配置

Spring Boot为Spring MVC提供自动配置,且适用于大多数应用程序。

自动配置在Spring默认配置基础上,添加了以下功能:

  • 包括:ContentNegotiatingViewResolver和BeanNameViewResolver bean。
  • 支持提供静态资源,包括对WebJars的支持。
  • 自动注册Converter,GenericConverter和Formatter bean。
  • 支持HttpMessageConverters。
  • 自动注册MessageCodesResolver(本文档后面会介绍)。
  • 静态 index.html 页面支持。
  • 自定义Favicon支持。
  • 自动使用ConfigurableWebBindingInitializer bean)。

如果要保留Spring Boot MVC功能并且想要添加其他MVC配置(interceptors,formatters,view controllers和其他功能),可以添加自己的@Configuration类,类型为WebMvcConfigurer,但不包含@EnableWebMvc。如果您希望可以自定义RequestMappingHandlerMapping,RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver实例,则可以声明WebMvcRegistrationsAdapter实例以提供此类组件。

如果您想完全控制Spring MVC,可以使用@EnableWebMvc添加自己的@Configuration注释。

以下正文,对上面标红的内容进行分析

正文

1- ContentNegotiatingViewResolver and BeanNameViewResolver beans

1-1-源码出处

public class WebMvcAutoConfiguration {
    //-在Springboot启动初始化时,自动装载WebMvcAutoConfiguration类,
    //其中包括WebMvcAutoConfiguration内部类WebMvcAutoConfigurationAdapter下的ContentNegotiatingViewResolver viewResolver()方法
    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware {

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

    }
}
public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport implements ViewResolver, Ordered, InitializingBean {
    //2-ContentNegotiatingViewResolver 执行其内部initServletContext()初始化方法,从BeanFactoryUtils中获取全部ViewResolver
    protected void initServletContext(ServletContext servletContext) {
        Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
        ViewResolver viewResolver;
        if (this.viewResolvers == null) {

            Iterator var3 = matchingBeans.iterator();
            while(var3.hasNext()) {
                viewResolver = (ViewResolver)var3.next();
                if (this != viewResolver) {
                    this.viewResolvers.add(viewResolver);
                }
            }
        }
        …………………………省略
    }

    //2-当一个请求进来时,调用ContentNegotiatingViewResolver 下的View resolveViewName()方法,,并返回bestView,主要包括beanName参数,即对应渲染的(比如:html)文件名称
    @Nullable
    public View resolveViewName(String viewName, Locale locale) throws Exception {
        //ContentNegotiatingViewResolver  根据文件名和请求头类型来决定返回什么样的View。而mediaTypes这个属性存储了 你请求后缀名 或者 参数 所对应 的mediaType
        RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
        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;
            }
        }
        ……………省略
    }

    //2-1-获取候选视图对象
    private List<View> getCandidateViews(String viewName, Locale locale, List<MediaType> requestedMediaTypes) throws Exception {
        List<View> candidateViews = new ArrayList();
        if (this.viewResolvers != null) {
            //获取全部视图解析器
            Iterator var5 = this.viewResolvers.iterator();
            //筛选出候选View
            while(var5.hasNext()) {
                …………………………省略
                while(var11.hasNext()) {
                    String extension = (String)var11.next();
                    String viewNameWithExtension = viewName + ‘.‘ + extension;
                    view = viewResolver.resolveViewName(viewNameWithExtension, locale);
                    if (view != null) {
                        candidateViews.add(view);//获取view
                    }
                }
            }

        }
        return candidateViews;
    }
}

1-2-源码解释

  • 1-在Springboot启动初始化时,自动装载WebMvcAutoConfiguration类,其中包括WebMvcAutoConfiguration内部类WebMvcAutoConfigurationAdapter下的ContentNegotiatingViewResolver viewResolver()方法
  • 2-ContentNegotiatingViewResolver 执行其内部initServletContext()初始化方法,从BeanFactoryUtils中获取全部ViewResolver
  • 3-当一个请求进来时,调用ContentNegotiatingViewResolver 下的View resolveViewName()方法根据方法的返回值得到视图对象(View),,并返回bestView,主要包括beanName参数,即对应渲染的(比如:html)文件名称

1-3-自定义视图解析器

1-3-1-自定义解析其源码

@SpringBootApplication
public class SpringbootdemoApplication {

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

    //在Springboot启动时,加载自定义的MyViewResolver类
    @Bean
    public ViewResolver myViewResolver(){
        return new MyViewResolver();
    }

    //(这里为了方便,在启动类下写了一个内部类)
    //MyViewResolver实现接口类ViewResolver
    private static class MyViewResolver implements ViewResolver{

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

}

1-3-2-源码解析

  • 1-自定义MyViewResolver 类必须实现ViewResolver接口
  • 2-并在Springboot初始化是,被自动加载

1-3-3-使用结果:在Spring分发请求时,发现自定义的MyViewResolver被被加载

2-支持提供静态资源,包括对WebJars的支持。请参考本人博客:https://www.cnblogs.com/wobuchifanqie/p/10112302.html

3-自动注册Converter,GenericConverter和Formatter bean

3-1-自定义Converter

//1-controller层
@Controller
public class DemoController {
    Logger log = LoggerFactory.getLogger(DemoController.class);

    @RequestMapping(value="get/student")
    public String getStudent(Student student,Model model){
        log.debug("student: " + student);
        model.addAttribute("student",student);
        return "student";
    }

}
//2-自定义converter
@Configuration
public class StringToStudentConverrter implements Converter<String,Student> {
    @Override
    public Student convert(String s) {
        //student=tyj-18
        String[] split = s.split("-");
        Student student = new Student(split[0],Integer.parseInt(split[1]));
        return student;
    }
}
//3-html示例<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div th:text="${student.name}"></div>
    <div th:text="${student.age}"></div>
    <strong>success!</strong>
</body>
</html>

4-支持HttpMessageConverters:SpringMVC用来转换Http请求和响应的;是从容器中确定;获取所有的HttpMessageConverter

4-2-自定义HttpMessageConverters

//1-自定义HttpMessageConverters
public class MyMessageConveter extends AbstractHttpMessageConverter<Student>{

    public MyMessageConveter() {
        //Content-Type= application/xxx-tyj
        super(new MediaType("application", "xxx-tyj", Charset.forName("UTF-8")));
    }

    @Override
    protected boolean supports(Class<?> aClass) {
        // 表明只处理UserEntity类型的参数。
        return Student.class.isAssignableFrom(aClass);
    }

    //重写readlntenal 方法,处理请求的数据。代码表明我们处理由“-”隔开的数据,并转成 Student类型的对象。
    @Override
    protected Student readInternal(Class<? extends Student> aClass, HttpInputMessage httpInputMessage)
            throws IOException, HttpMessageNotReadableException {
        String content = StreamUtils.copyToString(httpInputMessage.getBody(), Charset.forName("UTF-8"));
        String[] split = content.split("-");
        return new Student(split[0],Integer.parseInt(split[1]));
    }

    //重写writeInternal ,处理如何输出数据到response。
    @Override
    protected void writeInternal(Student student, HttpOutputMessage httpOutputMessage)
            throws IOException, HttpMessageNotWritableException {
            String out = "hello: " +student.getName() + " ,你今年" + student.getAge() + "了么?";
             httpOutputMessage.getBody().write(out.getBytes());
    }
}
//2-加载自定义的MyMessageConveter
@Configuration
public class MySpringBootConfig  {
    @Bean
    public MyMessageConveter MyMessageConveter (){
        return new MyMessageConveter();
    }
}
//3-controller
@Controller
public class DemoController {

    @RequestMapping(value="hello/student",method = POST)
    @ResponseBody
    public Student helloStudent(@RequestBody  Student student){
        return student;
    }

}
接口测试
URL:POST   localhost:8080/hello/student
header: Content-Type = application/xxx-tyj
body: tyj-21

返回值:hello: tyj ,你今年21了么?

4-3-添加一个converter的方式有三种

@Configuration
public class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
    // 添加converter的第一种方式,代码很简单,也是推荐的方式
    // 这样做springboot会把我们自定义的converter放在顺序上的最高优先级(List的头部)
    // 即有多个converter都满足Accpet/ContentType/MediaType的规则时,优先使用我们这个
    @Bean
    public MyMessageConveter MyMessageConveter (){
        return new MyMessageConveter();
    }
    // 添加converter的第二种方式
    // 通常在只有一个自定义WebMvcConfigurerAdapter时,会把这个方法里面添加的converter(s)依次放在最高优先级(List的头部)
    // 虽然第一种方式的代码先执行,但是bean的添加比这种方式晚,所以方式二的优先级 大于 方式一
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // add方法可以指定顺序,有多个自定义的WebMvcConfigurerAdapter时,可以改变相互之间的顺序
        // 但是都在springmvc内置的converter前面
        converters.add(new MyMessageConveter());
    }

    // 添加converter的第三种方式
    // 同一个WebMvcConfigurerAdapter中的configureMessageConverters方法先于extendMessageConverters方法执行
    // 可以理解为是三种方式中最后执行的一种,不过这里可以通过add指定顺序来调整优先级,也可以使用remove/clear来删除converter,功能强大
    // 使用converters.add(xxx)会放在最低优先级(List的尾部)
    // 使用converters.add(0,xxx)会放在最高优先级(List的头部)
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new MyMessageConveter());
    }
}

5-自动注册MessageCodesResolver:定义错误代码生成规则

6-静态 index.html 页面支持。请参考本人博客:https://www.cnblogs.com/wobuchifanqie/p/10112302.html

7-自定义Favicon支持。请参考本人博客:https://www.cnblogs.com/wobuchifanqie/p/10112302.html

8-自动使用ConfigurableWebBindingInitializer bean。

参考资料

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

2-http://www.cnblogs.com/huhx/p/baseusespringbootconverter1.html

3-https://www.cnblogs.com/page12/p/8166935.html

4-http://www.cnblogs.com/hhhshct/p/9676604.html

原文地址:https://www.cnblogs.com/wobuchifanqie/p/10123118.html

时间: 2024-08-07 22:44:02

SpringBoot学习-SpringMVC自动配置的相关文章

SpringBoot日记——SpringMvc自动配置与扩展篇

为了让SpringBoot保持对SpringMVC的全面支持和扩展,而且还要维持SpringBoot不写xml配置的优势,我们需要添加一些简单的配置类即可实现: 通常我们使用的最多的注解是: @Bean @Component 配置后的类就是我们要写在容器中的一些配置:详情后续再说,或者你也可以参考官方文档 关于扩展 这里我们说一下如何做扩展呢,先看一下原先在SpringMvc中我们是如何写的,来看XML(这是一段关于路径映射和拦截器的简单配置,访问hello路径也展示success.html的页

SpringBoot扩展SpringMVC自动配置

SpringBoot中自动配置了 ViewResolver(视图解析器) ContentNegotiatingViewResolver(组合所有的视图解析器) 自动配置了静态资源文件夹.静态首页.favicon.ico及Webjars Converter(转换器,转换类型使用) Formatter(格式化器) HttpMessageConverter(对SpringMVC的请求和响应进行序列化) MessageCodesResolver(定义错误代码生成规则) ConfigurableWebBi

Springboot学习~7:SpringMVC自动配置

Spring MVC auto-configuration Spring Boot 自动配置好了SpringMVC 以下是SpringBoot对SpringMVC的默认配置:==(WebMvcAutoConfiguration)== Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans. 自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转

尚硅谷springboot学习14-自动配置原理

配置文件能配置哪些属性 配置文件能配置的属性参照 自动配置的原理 1).SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration 2).@EnableAutoConfiguration 作用: 利用EnableAutoConfigurationImportSelector给容器中导入一些组件? 可以查看selectImports()方法的内容: List<String> configurations = getCandidateConfi

springBoot日志框架自动配置与原理

1.日志框架 小张:开发一个大型系统: ? 1.System.out.println(""):将关键数据打印在控制台:去掉?写在一个文件? ? 2.框架来记录系统的一些运行时信息:日志框架 : zhanglogging.jar: ? 3.高大上的几个功能?异步模式?自动归档?xxxx? zhanglogging-good.jar? ? 4.将以前框架卸下来?换上新的框架,重新修改之前相关的API:zhanglogging-prefect.jar: ? 5.JDBC---数据库驱动: ?

19-spring学习-springMVC环境配置

新建一共环境,添加spring支持,就可以开发springMVC了. 既然是springMVC,就必须为其定义相关配置. 1,springMVC所有配置都需要在applicationContext.xml中定义. 范例:修改配置文件 添加这几个支持: 发现配置中已经支持了 对springMVC进行annotation的配置 <!-- SpringMVC也是基于Annotaion实现的配置,启用annotation --> <context:annotation-config/> &

SpringBoot学习--01基础配置--maven配置

maven作为一个项目构建工具,在开发的过程中很受欢迎,可以帮助管理项目中的bao依赖问题,另外它的很多功能都极大的减少了开发的难度,下面来介绍maven的安装及与eclipse的集成. maven的官网地址为:http://maven.apache.org/ 下载步骤如下: 进入官网,点击下载 进入下载页面,点击镜像包 选择maven包 选择maven版本 选择压缩资源包 选择资源 由于maven需要JDK的支持,所以在安装maven之前请确保电脑上已经安装了JDK,且配置好了环境变量,具体的

SpringBoot源码学习系列之异常处理自动配置

1.源码学习 先给个SpringBoot中的异常例子,假如访问一个错误链接,让其返回404页面 在浏览器访问: 而在其它的客户端软件,比如postman软件: 很显然,在浏览器里访问才会返回页面,而在Postman直接返回json数据了,所以基于此现象,可以跟一下Springboot异常自动配置的原理,本博客基于学习了尚硅谷课程之后,自己动手实践再做的笔录 SpringBoot的异常自动配置类是ErrorMvcAutoConfiguration.java,可以简单跟一下源码: package o

SpringBoot——自动配置与启动

今天学习一下SpringBoot的自动配置与启动,由于没有参与过springBoot项目开发, 所以初次学习的主要目标:将SpringBoot中的自动配置与启动与之前学习的Spring与SpringMVC实现联系起来.弄清楚SpringBoot中的: SpringIOC容器初始化 SpringAOP支持 Spring事务支持 SpringMVC组件初始化 Tomcat启动 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12552114.html