博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
9 Web开发——springmvc自动配置原理
阅读量:7224 次
发布时间:2019-06-29

本文共 10340 字,大约阅读时间需要 34 分钟。

官方文档目录:

 

 

 1. Spring MVC auto-configuration

  Spring Boot 自动配置好了SpringMVC,以下是SpringBoot对SpringMVC的默认配置:

WebMvcAutoConfiguration)

  - Inclusion of `ContentNegotiatingViewResolver` and `BeanNameViewResolver` beans.

  - 自动配置了ViewResolver视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))

    • public class WebMvcAutoConfiguration {        @Bean        @ConditionalOnMissingBean        public InternalResourceViewResolver defaultViewResolver() {            InternalResourceViewResolver resolver = new InternalResourceViewResolver();            resolver.setPrefix(this.mvcProperties.getView().getPrefix());            resolver.setSuffix(this.mvcProperties.getView().getSuffix());            return resolver;        }        @Bean        @ConditionalOnBean({View.class})        @ConditionalOnMissingBean        public BeanNameViewResolver beanNameViewResolver() {            BeanNameViewResolver resolver = new BeanNameViewResolver();            resolver.setOrder(2147483637);            return resolver;        }        @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;        }    ......}

    - :只配置一个@RequestMapping, 匹配多个 url

  • public class ContentNegotiatingViewResolver implements ViewResolver, Ordered, InitializingBean {
    @Nullable    privateList
    viewResolvers; //视图解析器 //初始化方法 protected void initServletContext(ServletContext servletContext) { //从容器中根据ViewResolver类型获取所有的视图解析器Collection
    matchingBeans = BeanFactoryUtils .beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values(); ViewResolver viewResolver; 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); } @Nullable publicView resolveViewName(String viewName, Locale locale) throws Exception { RequestAttributes attrs = RequestContextHolder.getRequestAttributes(); Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes"); List
    requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest()); if (requestedMediaTypes != null) {
    //只配置一个@RequestMapping, 匹配多个 url,所以要获取多个 List
    candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);//获取所有候选的视图对象 View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);//获取最佳视图对象(根据参数或类型选取) if (bestView != null) { return bestView; } }}
  • 自定义ViewResolver加入到Spring容器
  • //springBoot启动类注解,包含@Configuration@SpringBootApplicationpublic class DemoApplication {    public static void main(String[] args) {        SpringApplication.run(DemoApplication.class, args);    }    //将自定义的ViewResolver加入到Spring容器中    @Bean    public ViewResolver myViewResolver() {        return new MyViewResover();    }    //自定义ViewResover    public static class MyViewResover implements  ViewResolver {        @Nullable        @Override        public View resolveViewName(String s, Locale locale) throws Exception {            return null;        }    }}
  •  当SpringBoot项目启动,随便发一个请求,进到DispatcherServlet的DoDispatch()方法时,能够获取到所有的ViewResolver,包括自定义的,被包含在了ContentNegotiatingViewResolver里

     

 

 

  - 总结:如何定制视图解析器ViewResolver?

    根据@WebMvcAutoConfiguration

        ——》 @Bean ContentNegotiatingViewResolver viewResolver()

            ——》initServletContext()中根据类型加载容器中所有的ViewResolver

    我们可以自己给容器中添加一个视图解析器,@Bean加入到容器中,SpringBoot便自动的将其组合进来;   关于视图解析器详情在SprintMVC知识点中学习

 这些前面章节已有学过

  - Support for serving static resources, including support for WebJars (see below).静态资源文件夹路径,webjars

  - Static `index.html` support. 静态首页访问

  - Custom `Favicon` support (see below). favicon.ico

 


 

- 自动注册了 of `Converter`, `GenericConverter`, `Formatter` beans.

 

  - Converter:转换器; public String hello(User user):类型转换使用Converter      (如果页面传参和User对象类型一一对应,不用转换,如果对应不上就需要转换)

  - `Formatter` 格式化器; 2017.12.17   /   2017-12-17  / 2017/12/17===Date;  (1:字符串转日期;2:按照给定的格式转)

    •     

 

 

@Configuration@ConditionalOnWebApplication(        type = ConditionalOnWebApplication.Type.SERVLET)@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})@AutoConfigureOrder(-2147483638)@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})public class WebMvcAutoConfiguration {    @Configuration    @Import({org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})    @EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})    @Order(0)    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware {        private final ListableBeanFactory beanFactory;        @Bean        public FormattingConversionService mvcConversionService() {            WebConversionService conversionService = new WebConversionService(this.mvcProperties.getDateFormat());            this.addFormatters(conversionService);            return conversionService;        }        protected void addFormatters(FormatterRegistry registry) {            this.configurers.addFormatters(registry);        }        //添加格式化器        public void addFormatters(FormatterRegistry registry) {            //容器中符合Converter类型的bean都被格式化注册器FormatterRegistry注册进来            Iterator var2 = this.getBeansOfType(Converter.class).iterator();            while(var2.hasNext()) {                Converter
converter = (Converter)var2.next(); registry.addConverter(converter); } //容器中符合GenericConverter类型的bean都被格式化注册器FormatterRegistry注册进来 var2 = this.getBeansOfType(GenericConverter.class).iterator(); while(var2.hasNext()) { GenericConverter converter = (GenericConverter)var2.next(); registry.addConverter(converter); } //容器中符合Formatter类型的bean都被格式化注册器FormatterRegistry注册进来 var2 = this.getBeansOfType(Formatter.class).iterator(); while(var2.hasNext()) { Formatter
formatter = (Formatter)var2.next(); registry.addFormatter(formatter); } /** * 从容器中获取所有从属于此类型的Bean * 自己添加的格式化器转换器,我们只需要放在容器中即可 */ private
Collection
getBeansOfType(Class
type) { return this.beanFactory.getBeansOfType(type).values(); } } }}

 

  - HttpMessageConverter:SpringMVC用来转换Http请求和响应的;返回结果将  User    ——》转化为  Json;

  - `HttpMessageConverters` 是从容器中确定;获取所有的HttpMessageConverter;

 

 

 

  •            
  • //@Configuration包含了@Component@Configurationpublic class WebMvcAutoConfiguration {    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware {        private final ObjectProvider
    messageConvertersProvider; //通过构造方法从容器中注入进来 public WebMvcAutoConfigurationAdapter(ObjectProvider
    messageConvertersProvider,其它参数) { this.messageConvertersProvider = messageConvertersProvider; ...... } }}//@Configuration包含了@Component@Configurationpublic class HttpMessageConverters implements Iterable
    > { private final List
    > converters; // public HttpMessageConverters(HttpMessageConverter... additionalConverters) { this((Collection) Arrays.asList(additionalConverters)); } //通过构造方法从容器中注入进来 public HttpMessageConverters(Collection
    > additionalConverters) { this(true, additionalConverters); }}

     自己给容器中添加HttpMessageConverter,只需要将自己的组件注册容器中(@Bean,@Component)

 

  - Automatic registration of `MessageCodesResolver` (see below).定义错误代码生成规则

  - Automatic use of a `ConfigurableWebBindingInitializer` bean (see below).

    我们可以配置一个ConfigurableWebBindingInitializer来替换默认的;(添加到容器)

      ```初始化WebDataBinder;

      ```请求数据=====JavaBean;

 

 

 

If you want to keep Spring Boot MVC features and you want to add additional  (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.


 

 总结:如何修改SpringBoot的默认配置?

​   1)、SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,

    如果没有,才自动配置;

    如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来;

转载于:https://www.cnblogs.com/guchunchao/p/9898270.html

你可能感兴趣的文章
“域控制器安全策略”打开错误的解决方法
查看>>
为SharePoint搜索创建自定义优化参数
查看>>
linux文件
查看>>
Exchange Powershell查看用户最后登陆邮箱时间
查看>>
我所认识的ELK Stack
查看>>
聊下 git remote prune origin
查看>>
Java线程:线程的调度-守护线程
查看>>
[职业发展]中国本科生的6大软肋,彰显就业意识不强
查看>>
每个IIS中发布的网站只能绑定 一个端口
查看>>
Activiti源码分析
查看>>
WPF异步MVVM等待窗体
查看>>
安卓播放视频
查看>>
java.io.IOException: This archive has already been finished
查看>>
71.7. Script for automatic startup on boot
查看>>
CentOS 7.4 安装php 配置php-fpm服务
查看>>
66.4. RMAN
查看>>
正则表达式替换器 RegeX 3 发布 (Silverlight版)
查看>>
JavaMelody监控SQL
查看>>
Gym 100952H&&2015 HIAST Collegiate Programming Contest H. Special Palindrome【dp预处理+矩阵快速幂/打表解法】...
查看>>
Oozie分布式任务的工作流——Sqoop篇
查看>>