最近看了《Spring in Action》的开头,就被Spring注解开发(完全不写web.xml)惊叹了,也第一次知道了@EnableWebMvc是SpringMVC的注解

@EnableWebMvc注解

@EnableWebMvc的javaDoc注释有点长。  从下图得到的几个信息: href="mailto:1.@EnableWebMvc">1.@EnableWebMvc没有任何属性,只是@Import了一个类叫DelegatingWebMvcConfiguration

2. 注释中说明:将@EnableWebMvc添加给@Configuration类来导入SpringMvc的配置;3.自定义MVC配置,实现接口WebMvcConfigurer或更可能继承WebMvcConfigurerAdapter,并且使用@EnableWebMvc;

4.如果还想要自定义配置,移除@EnableWebMvc,并且继承WebMvcConfigurationSupport或DelegatingWebMvcConfiguration。

5.@EnableWebMvc出现自Spring3.1的版本


@EnableWebMvc的注释文档说的很详细,先记录第一点,@Import的类是干啥的!

@Import的多种用法看我这篇文档:Spring @Import .   @Import导入了一个类DelegatingWebMvcConfiguration,这个类标注了@Configuration类,这个类下方法上标注了@Bean的都会纳入Spring容器管理。

DelegatingWebMvcConfiguration类如下,但是类里面搜索却没有@Bean标注! 在其父类WebMvcConfigurationSupport里面搜索到了19个@Bean.

这19个@Bean基本上和<mvc:annotation-driven/>实现的功能无差,甚至提供了一种很便捷的方式扩展<mvc:annotation-driven/>

举两个栗子,说明下:1. <mvc:annotation-driven/> @ResponseBody 返回String中文乱码  Spring @ResponseBody String中文乱码

@EnableWebMvc同样存在这个问题,默认字符集为ISO-8859-1,解决方案:继承WebMvcConfigurerAdapter,重写extendMessageConverters方法!

栗子2:比如需要添加拦截器,原先写法可能是<mvc:interceptors></mvc:interceptors>这种形式添加,现在不用XML,方式就是这样:

在继承WebMvcConfigurerAdapter基础上,重写addInterceptor方法。


@EnableWebMvc可扩展的结构

图片可以从processOn拷贝,RequestMappingHandlerMapping地址:https://www.processon.com/view/5c9d8480e4b035b243ba651b

RequestMappingHandlerAdapter地址:https://www.processon.com/view/5c9d86cee4b034408de5663d  红框代表可继承扩展WebMvcConfigurerAdapter等扩展的方法。

想到为什么继承WebMvcConfigurerAdapter或者实现WebMvcConfigurer,就能够在@EnableWebMvc继承上扩展呢?

@EnableWebMvc导入的是DelegatingWebMvcConfiguration类,和WebMvcConfigurer完全没有联系啊?

说明:DelegatingWebMvcConfiguration类,有这样一个属性WebMvcConfigurerComposite,维护着WebMvcConfigurer的集合,有点类似组合模式。

初始化DelegatingWebMvcConfiguration时如果发现了WebMvcConfigurer的实现类,就注入到WebMvcConfigurerComposite中,这样就把我们实现了WebMvcConfigurer的类和@EnableWebMvc联系到一起了,

就可以在<mvc:annotation-driven/>基础上扩展.

这里很神奇,在我理解中Spring没法自动判断两个Bean作为集合注入的啊! 这里起作用的就是required=false  少了这句话就抛出异常!


@EnableWebMvc默认是没有静态资源放行的,比如.css  .js文件默认  也会被 dispatchServelt   / 形式的拦截到

原来在web.xml文件中可以这样配置,静态资源后缀为.js  .css不拦截

       <servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>*.htm</url-pattern>
<url-pattern>*.css</url-pattern>
<url-pattern>*.js</url-pattern>
</servlet-mapping>

在没有web.xml的文件中解决方案:继承WebMvcConfigurerAdapter,并且重写configureDefaultServletHandling方法,即可达到和上面一样的效果,就可以访问 .css .js等文件!

原理解析:如果这篇博客前面看过了,直接看到WebMvcConfigurationSupport,@Bean注册了一个bean  defaultServletHandlerMapping,最终configureDefaultServletHandling会制定我们上面的方法。

DefaultServletHandlerConfigurer只是个配置类,Bean实际返回的是hanlderMapping!=null?handlerMapping:new EmptyHandlerMapping();  EmptyHandlerMapping不对请求做任何处理,而configurer的getHandlerMapping方法如下: handler不为空,就会返回一个SimpleUrlHandlerMapping,而configurer.enable()方法等价于configurer.enable(null),就是初始化handler的。总的来说就是,configurer.enable()方法就是注册了一个SimpleUrlHandlerMapping对象,handler就是DefaultServletHttpRequestHandler.

DefaultServletHttpRequestHandler如何处理静态资源请求?

通过获取 服务器默认的servlet进行转发,因为/** 会匹配所有的URI,所以SimpleUrlHandlerMapping必须放在RequestMappingHandlerMapping之后;核心方式就是servletContext.getNamedDispatcher(“default”).forward(request,response);

总结@EnableWebMvc替我们做了什么?

引入了这样一个类DelegatingWebMvcConfiguration,通过@Bean注册了和<mvc:annotation-driven/>一样的组件,RequestMappingHandlerMapping、RequestMappingHandlerAdatper、HandlerExceptionResolver等等,只要有个Spring管理的bean继承WebMvcConfigurer或WebMvcConfigurerAdapter,重写方法即可自定义<mvc:annotation-driven/>.

其实@EnableWebMvc == @Import({DelegatingWebMvcConfiguration.class})

详解@EnableWebMvc的更多相关文章

  1. Spring MVC 学习总结(二)——控制器定义与@RequestMapping详解

    一.控制器定义 控制器提供访问应用程序的行为,通常通过服务接口定义或注解定义两种方法实现. 控制器解析用户的请求并将其转换为一个模型.在Spring MVC中一个控制器可以包含多个Action(动作. ...

  2. Spring Boot异常处理详解

    在Spring MVC异常处理详解中,介绍了Spring MVC的异常处理体系,本文将讲解在此基础上Spring Boot为我们做了哪些工作.下图列出了Spring Boot中跟MVC异常处理相关的类 ...

  3. Spring MVC测试框架详解——服务端测试

    随着RESTful Web Service的流行,测试对外的Service是否满足期望也变的必要的.从Spring 3.2开始Spring了Spring Web测试框架,如果版本低于3.2,请使用sp ...

  4. SpringMvc测试框架详解----服务端测试

    随着RESTful Web Service的流行,测试对外的Service是否满足期望也变的必要的.从Spring 3.2开始Spring了Spring Web测试框架,如果版本低于3.2,请使用sp ...

  5. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  6. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  7. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  8. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  9. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

随机推荐

  1. 【Spark2.0源码学习】-8.SparkContext与Application介绍

             在前面的内容,我们针对于RpcEndpoint启动以及RpcEndpoint消息处理机制进行了详细的介绍,在我们的大脑里,基本上可以构建Spark各节点的模样.接下来的章节将会从Sp ...

  2. ulogd(一)

    参考资料: https://blog.csdn.net/eydwyz/article/details/52456335 https://blog.csdn.net/chinalinuxzend/art ...

  3. 【APP测试(Android)】--硬件测试

  4. Spring AOP配置方式

    AOP 面向切面编程,允许在 java 应用中的方法调用的前后做一些处理. 本文通过实例介绍两种主要的Spring AOP 配置方式:xml 方式配置,注解方式配置 XML 方式配置 1. 项目包类结 ...

  5. Codeforces 1082C Multi-Subject Competition 前缀和 A

    Codeforces 1082C Multi-Subject Competition https://vjudge.net/problem/CodeForces-1082C 题目: A multi-s ...

  6. 曙光服务器挂载EMC存储

    1.登录集群(用户名密码远程登录,然后切换到root用户) 2.连接主机:ssh node72 3.在主机下进行存储挂载: 1)fdisk -l 查看磁盘信息,如下图所示: 2)查看磁盘挂载信息:mo ...

  7. 部署eclipse项目到tomcat

    1.为了以防万一,将本地tomcat版本及其jdk版本与服务器上的版本最好是相同的 2.在本地eclipse下运行项目即可发布(注意(1)数据库连接的是服务器数据库还是本地数据库(2)运行项目前先cl ...

  8. 【jenkins git】Failed to connect to repository:Error performing command:git.exe ls-remote-h

    jenkins使用git源码管理报错:Failed to connect to repository:Error performing command:git.exe ls-remote-h 本机需要 ...

  9. [Project] SpellCorrect源码详解

    该Project原来的应用场景是对电商网站中输入一个错误的商品名称进行智能纠错,比如iphoae纠错为iphone.以下介绍的这个版本对其作了简化,项目源代码地址参见我的github:https:// ...

  10. H5+.Net Webapi集成微信分享前后端代码 微信JS-SDK wx.onMenuShareTimeline wx.onMenuShareAppMessage

    说明: 1/因为赚麻烦这里没有使用数据库或服务器缓存来存储access_token和jsapi_ticket,为了方便这里使用了本地的xml进行持久化这两个值以及这两个值的创建时间和有限期限. 2/每 ...